القواميس والمجموعات
خزّن التعيينات الرئيسية بالقواميس، والعناصر الفريدة بالمجموعات.
- إنشاء القواميس والوصول إلى القيم وتعديلها
- فهم متطلبات صلاحية مفاتيح القاموس
- استخدام المجموعات للفردية واختبار العضوية
- التكرار عبر القواميس والمجموعات
الاقتران
يسمّي الرياضيونُ جدولًا يقترن فيه كلُّ مدخلٍ بمخرجٍ واحدٍ دالةً؛ وتسمّيه بايثون قاموسًا. المفاتيحُ تشيرُ إلى قيمٍ، تمامًا كما يشير قاموسُ الكلماتِ إلى تعريفاتها:
scores = {"Alice": 85, "Bob": 92, "Charlie": 78}
print(scores["Alice"]) # 85
print(scores.get("Dave", 0)) # 0 (القيمة الافتراضية عند غياب المفتاح)الفهرسةُ بـ [] هي البحثُ النفور: تشترط وجودَ المفتاح. و.get(key, default) هي الصيغةُ المهذّبة: إن غاب المفتاحُ فترجع البديلَ بدلًا من رمي KeyError. والتفرقةُ هي الفرقُ بين دعوى وسؤالٍ.
عدةُ القاموس
scores = {"Alice": 85, "Bob": 92}
scores.keys() # dict_keys(['Alice', 'Bob'])
scores.values() # dict_values([85, 92])
scores.items() # dict_items([('Alice', 85), ('Bob', 92)])
scores["Dave"] = 78 # يضيف زوجًا جديدًا
del scores["Bob"] # يحذف بمفتاحه
scores.pop("Alice") # يحذف ويرجع القيمة
scores.update({"Eve": 95, "Frank": 88}) # يدمج
scores.setdefault("Grace", 0) # يخصص فقط إن غاب المفتاحإنّ keys وvalues وitems ثلاثُ مناظرَ للعلاقة نفسها ، المجالُ، والمدى، والرسمُ البياني. يدمج update قاموسًا ثانيًا؛ ويكتب setdefault فقط حين يغيب المفتاحُ، الإسنادَ المشروطَ الذي لا يحتاج if.
التجوّل على الاقتران
إنّ التكرارَ على قاموسٍ يجوب المجالَ افتراضيًّا؛ ولترى النصفين معًا فاطلب items:
for name in scores: # المفاتيح
print(name)
for name, score in scores.items(): # أزواج المفتاح-القيمة
print(f"{name}: {score}")يُسلّمك items الزوجَ مباشرةً ، بلا فهرسةٍ يدوية ، إذ إن تفكيكَ مدخلٍ إلى name, score هو القراءةُ الطبيعيَّةُ لصفٍّ.
المجموعات: مجموعةُ الرياضيات
المجموعةُ مجموعةٌ بالمعنى الرياضي: تجميعٌ بلا ترتيبٍ وبلا تكرارٍ. يذوب التكرارُ عند الباب:
colors = {"red", "blue", "green", "red"}
print(colors) # {'red', 'blue', 'green'} (حُذفت التكرارات)الفرديةُ مفروضةٌ بنيويًّا ، لا نسخةٌ ثانيةٌ تنتظر تلويثَ فحصِ العضوية. والعضويةُ في مجموعةٍ هي تمامًا: العنصرُ داخلٌ أو خارجٌ، بلا مرتبةِ وسطى.
عمليات المجموعات
جبرُ المجموعات منسوجٌ مباشرةً. مع و:
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
a | b # {1, 2, 3, 4, 5, 6} (الاجتماع)
a & b # {3, 4} (التقاطع)
a - b # {1, 2} (الفرق)
a ^ b # {1, 2, 5, 6} (الفرق المتناظر)العواملُ هي العلاماتُ التي تعرفها مسبقًا. وحيث يعدُّ النظريةُ بالسرعة، يوفّي التنفيذُ بوعدِه: فحصُ العضويةِ في مجموعةٍ يجري في مقابلَ للقائمة، لأن المجموعةَ تخزّن العناصرَ ببصمةٍ محسوبةٍ لا بموقعٍ.
شرطُ البصمة
البصماتُ تشترطُ الاستقرارَ. يجب أن تكون مفاتيحُ القاموسِ وعناصرُ المجموعاتِ قابلةً للبصم (hashable) ، عمليًّا، غيرَ قابلةٍ للتغيير ، لتظلَّ حساباتُها قابلةَ الإعادة. السلاسلُ والأعدادُ والجداولُ تفي؛ والقوائمُ وسائرُ القواميسِ لا تفي:
{[1, 2]: "bad"} # TypeError: unhashable type: 'list'
{(1, 2): "good"} # يعمل — الجَدْوِلُ قابلٌ للبصمما كانت قائمةٌ لتصلح مفتاحًا موثوقًا ولو أُذن بها: بصمتُها تتغيّرُ في اللحظةِ التي يتغير فيها محتواها، محوِّلةً الاقترانَ إلى حقلِ ألغامِ بحثٍ بائد.
مثالٌ محلول: دفترُ الدرجات
العلاقةُ والمجالُ والمدى ، جدولٌ واحدٌ يُقاسُ بثلاثِ وقفاتٍ:
scores = {"Alice": 85, "Bob": 92, "Charlie": 78}
for name, score in scores.items():
print(f"{name}: {score}")
print(scores.get("Dave", "absent")) # absent — بلا KeyError
roles = {"student", "teacher", "admin"}
print("student" in roles) # True — انتماءٌ O(1)يمشي items الرسمَ كلَّهُ، ويستعلمُ .get بلطفٍ حين تجهلُ وجودَ المفتاحِ، وin على مجموعةٍ هو الانتماءُ ، ثلاثةُ أسئلةٍ تجيبُ عنها هياكلُ الدرسِ مباشرةً.
أخطاء شائعة
- الوصولُ إلى مفاتيحَ غائبة.
.get()أو فحصٌ بـinيوفران عليكKeyError. - الاتكاءُ على ترتيبِ القاموس. تحفظ بايثون 3.7+ ترتيبَ الإدراج، لكن أعامله تسهيلًا لا عقدًا.
- الثقةُ بترتيبِ مجموعةٍ. لا تحفظ المجموعةُ أيَّ ترتيبٍ؛ لا تجعلْ ترتيبَ التكرارِ قطُّ اعتمادًا.
{}قاموسٌ فارغٌ؛ وset()هو المجموعةُ الفارغة.{}ليست مجموعةً. اكتبْset()للفارغةِ وللحرفيةِ{"a", "b"}، رمزٌ واحدٌ بمعنيينِ.
🧩 تحديات
🧩 تحدٍّ ، فكّر أولًا ثم أظهر
عُدّ تكرارَ كلِّ حرفٍ في "hello world" بقاموسٍ.
💡 الجواب: freq = {}; for c in "hello world": freq[c] = freq.get(c, 0) + 1 ، بديلُ .get بـ $0$ يحوّل الظهورَ الأولَ إلى زيادةٍ من الصفر.
🧩 تحدٍّ ، فكّر أولًا ثم أظهر
بقائمتين، ابحث عن العناصرِ الظاهرةِ فيهما معًا باستخدامِ المجموعات.
💡 الجواب: set(a) & set(b) أو set(a).intersection(b) ، التقاطعُ هو $A \cap B$، وآلةُ المجموعاتِ تنجز العملَ.
🤔 أسئلة سقراطية
- لماذا لا تصلح قائمةٌ مفتاحًا لقاموسٍ؟ وما الصفةُ التي يجب أن يحملها المفتاح؟
- متى تتفوق مجموعةٌ على قائمةٍ ، ماذا تخسر وماذا تربح؟
- كيف يختلف
dict.get(key, default)عنdict[key]، ومتى تفضّل المرء؟
✅ فحص سريع
١. ماذا ترجع {"a": 1, "b": 2}.get("c", 0)؟
٢. ما قيمة {1, 2, 3} ^ {2, 3, 4}؟