مقارنة الحاويات والشاملات الشاملة
غطينا القوائم والصفوف والقواميس والمجموعات بشكل فردي. الآن دعنا نقوم بمقارنة جنباً إلى جنب — ما هي الاختلافات، ومتى يجب استخدام كل منها؟ سنتقن أيضاً الشاملات، واحدة من أقوى ميزات بايثون.
1. مقارنة الحاويات الأربع
| الميزة | قائمة (list) |
صف (tuple) |
قاموس (dict) |
مجموعة (set) |
|---|---|---|---|---|
| الصيغة | [] |
() |
{key: value} |
{} أو set() |
| مرتبة | ✅ نعم | ✅ نعم | ✅ ترتيب الإدراج (3.7+) | ❌ غير مرتبة |
| قابلة للتعديل | ✅ | ❌ | ✅ | ✅ |
| التكرارات | ✅ مسموح | ✅ مسموح | المفاتيح فريدة، القيم قد تتكرر | ❌ عناصر فريدة |
| الوصول | فهرس [0] |
فهرس [0] |
مفتاح ["key"] |
لا يدعم الفهرسة |
| سرعة البحث | O(n) بطيء | O(n) بطيء | O(1) سريع جداً | O(1) سريع جداً |
| الاستخدام النموذجي | بيانات مرتبة، مجموعات ديناميكية | بيانات ثابتة، إرجاعات دوال | تعيينات، تخزين مؤقت | إزالة تكرار، عمليات مجموعات |
مثال: مقارنة اختيار الحاوية (الصعوبة ⭐⭐)
# نفس السيناريو منفذ بحاويات مختلفة
# السيناريو: تخزين أسماء الطلاب
# قائمة — مرتبة، سهلة الإضافة/الإزالة
students_list = ["Alice", "Bob", "Charlie"]
students_list.append("Diana")
print(f"List: {students_list[0]}") # Alice
# صف — ثابت (مثل قائمة الفصل)
students_tuple = ("Alice", "Bob", "Charlie")
# students_tuple[0] = "xxx" # خطأ! الصفوف غير قابلة للتعديل
print(f"Tuple: {students_tuple[0]}") # Alice
# قاموس — بحث سريع بالمعرف
students_dict = {
"001": "Alice",
"002": "Bob",
"003": "Charlie",
}
print(f"Dict: {students_dict['002']}") # Bob — سرعة O(1)
# مجموعة — إزالة التكرارات (مثل قائمة الحضور)
attendance = {"Alice", "Bob", "Charlie", "Alice"}
print(f"Set: {attendance}") # {'Bob', 'Charlie', 'Alice'} — أزيل تكرار Alice
2. شاملات القوائم المتقدمة
الدرس 11 غطى الشاملات الأساسية. دعنا نتعمق أكثر.
شروط متعددة
numbers = range(1, 31)
# يقبل القسمة على 3 AND على 5
filtered = [n for n in numbers if n % 3 == 0 and n % 5 == 0]
print(filtered) # [15, 30]
# يقبل القسمة على 3 OR على 5
filtered = [n for n in numbers if n % 3 == 0 or n % 5 == 0]
print(filtered) # [3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24, 25, 27, 30]
شاملات الحلقات المتداخلة
# أنشئ أزواج إحداثيات — تعادل حلقة for مزدوجة
pairs = [(x, y) for x in range(3) for y in range(3)]
print(pairs)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# متداخلة مع شرط — ابحث عن الأزواج حيث المجموع زوجي
pairs = [(x, y) for x in range(3) for y in range(3) if (x + y) % 2 == 0]
print(pairs)
# [(0, 0), (0, 2), (1, 1), (2, 0), (2, 2)]
if-else في الشاملات
# if-else في الشاملات — لاحظ الموضع المختلف
numbers = [1, 2, 3, 4, 5, 6]
# فقط if (تصفية) — يوضع بعد
evens = [n for n in numbers if n % 2 == 0]
# if-else (تحويل) — يوضع قبل
result = ["even" if n % 2 == 0 else "odd" for n in numbers]
print(result) # ['odd', 'even', 'odd', 'even', 'odd', 'even']
مثال: خط أنابيب تحويل البيانات (الصعوبة ⭐⭐⭐)
# سطر واحد: تصفية → تحويل → تنسيق
raw = [" apple ", "BANANA", "", " CHERRY", None, " date "]
# صفّي None والسلاسل الفارغة → أزل المسافات → كبّر أول حرف
cleaned = [item.strip().capitalize() for item in raw if item and item.strip()]
print(cleaned) # ['Apple', 'Banana', 'Cherry', 'Date']
المخرجات:
['Apple', 'Banana', 'Cherry', 'Date']
3. شاملات القاموس
يمكن للقواميس أيضاً استخدام الشاملات. الصيغة مشابهة للقوائم، لكنها تستخدم {} وتحدد أزواج المفتاح-القيمة:
# شاملات القاموس الأساسية
squares = {x: x ** 2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# مع شرط
even_squares = {x: x ** 2 for x in range(10) if x % 2 == 0}
print(even_squares) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
# عكس المفاتيح والقيم
original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {value: key for key, value in original.items()}
print(reversed_dict) # {1: 'a', 2: 'b', 3: 'c'}
عملي: دمج قائمتين في قاموس
# ادمج قائمتين في قاموس
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
result = {names[i]: scores[i] for i in range(len(names))}
print(result) # {'Alice': 85, 'Bob': 92, 'Charlie': 78}
# استخدام zip() أكثر أناقة
result = {name: score for name, score in zip(names, scores)}
print(result) # {'Alice': 85, 'Bob': 92, 'Charlie': 78}
4. شاملات المجموعات
شاملات المجموعات تستخدم {} مع تعبير فقط (بدون نقطتين) — الفرق عن شاملات القاموس هو وجود أو عدم وجود نقطتين:
# شاملة مجموعة — إزالة التكرارات تلقائياً
numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5]
unique_squares = {x ** 2 for x in numbers}
print(unique_squares) # {1, 4, 9, 16, 25}
# مع شرط
even_set = {x for x in range(20) if x % 2 == 0}
print(even_set) # {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}
[x for x in ...] هي قائمة — مرتبة، التكرارات مسموحة. {x: y for x in ...} هو قاموس — به نقطتان. {x for x in ...} هي مجموعة — بدون نقطتين، غير مرتبة، بدون تكرارات.
حالات الاستخدام الشائعة
- خط أنابيب تنظيف البيانات: شاملة قائمة لتصفية القيم الفارغة وإزالة المسافات وتحويل التنسيق في سطر واحد.
- عكس تعيين القاموس: شاملة قاموس لتبديل المفاتيح والقيم للبحث العكسي.
- عد إزالة التكرارات: شاملة مجموعة لإحصائيات العناصر الفريدة السريعة.
- التجميع الشرطي: شاملات if-else لتقسيم البيانات إلى مجموعتين (مثل "نجاح/رسوب").
- توليد الإحداثيات: شاملات متداخلة لإحداثيات رقعة الشطرنج، شبكات البكسل، إلخ.
❓ أسئلة شائعة
[x for x in range(10)] تُنشئ جميع البيانات مرة واحدة في الذاكرة. تعبيرات المولدات (x for x in range(10)) كسولة — قيمة واحدة في كل مرة، توفر الذاكرة. استخدم المولدات لمجموعات البيانات الكبيرة (عشرات الآلاف+).
⚠️ س:ماذا لو كانت الشاملة تحتوي على أكثر من مستويين من التداخل؟ ج:الشاملات التي تحتوي على أكثر من مستويين تصبح غير قابلة للقراءة. كود مثل [x for xs in matrix for ys in xs for x in ys] يكاد يكون مستحيل الفهم للوهلة الأولى. إذا كنت بحاجة لثلاثة+ مستويات، استخدم حلقات for العادية أو دوال مساعدة.
س:كيف أقرر أي حاوية يجب استخدامها؟ ج:ثلاثة أسئلة: ① هل تحتاج مفاتيح فريدة؟ → قاموس. ② هل تحتاج إزالة تكرار أو عمليات مجموعات؟ → مجموعة. ③ هل تحتاج البيانات إلى التغيير؟ → قائمة إذا نعم، صف إذا لا. في معظم السيناريوهات، القوائم والقواميس تغطي 90% من حالات الاستخدام.📖 ملخص
- القوائم مرتبة وقابلة للتعديل؛ الصفوف مرتبة وغير قابلة للتعديل؛ القواميس هي مفتاح-قيمة مع بحث سريع؛ المجموعات لإزالة التكرار والعمليات الرياضية
- شاملة قائمة:
[expression for variable in iterable if condition] - شاملة قاموس:
{key: value for variable in iterable if condition} - شاملة مجموعة:
{expression for variable in iterable if condition} ifبعد الحلقة للتصفية؛if-elseقبل الحلقة للتحويل- الشاملات المتداخلة يمكنها توليد بيانات ثنائية الأبعاد، لكن أكثر من مستويين يتطلب حلقات عادية
📝 تمارين
-
أساسي (الصعوبة ⭐): استخدم شاملة قائمة لتوليد جميع الأرقام بين 10 و 50 التي تقبل القسمة على 7 أو تحتوي على الرقم 7. تلميح: استخدم
orلدمج شرطين. -
متوسط (الصعوبة ⭐⭐): بالنظر إلى قائمتين
keys = ["name", "age", "city"]وvalues = ["Alice", 25, "Beijing"]، استخدم شاملة قاموس لدمجهما في قاموس. تلميح: استخدمzip(keys, values)لربطهما. -
تحدي (الصعوبة ⭐⭐⭐): اكتب "محلل بيانات." بالنظر إلى سلسلة تحتوي على عدة جمل، احسب وأخرج: إجمالي عدد الكلمات، عدد الكلمات الفريدة، والكلمات الثلاث الأكثر تكراراً. تلميح: استخدم
split()للتقسيم، قاموساً للعد، وsorted(dict.items(), key=lambda x: x[1], reverse=True)[:3]لأول 3.



