قاموس بايثون: جدول بحث بالمفاتيح
القائمة في بايثون تُفهرس بالموقع (الرقم)، أما قاموس بايثون (أو ما يُعرف بـ dict) فيُفهرس بالـ_مفتاح_ — وغالبًا يكون نصًا أو رقمًا — وكل مفتاح يشير إلى قيمة معينة. هذا التحوّل البسيط يفتح لك بابًا واسعًا من التطبيقات: المخزون، ملفات الإعدادات، بيانات JSON، ملفات المستخدمين، والذاكرة المؤقتة (cache).
يمكن أن تكون المفاتيح والقيم أي شيء تقريبًا. شرط المفتاح الوحيد هو أن يكون قابلًا للتجزئة (hashable)، يعني: أرقام، نصوص، أو tuples — أما القوائم والقواميس الأخرى فلا تصلح كمفاتيح. القيم فلا قيود عليها إطلاقًا، فالقاموس يقبل أي نوع من البيانات، بما في ذلك قواميس أخرى أو قوائم متداخلة.
إنشاء قاموس في بايثون
في أكثر من طريقة لإنشاء قاموس بايثون، ولكل واحدة استخدامها المناسب:
قراءة القيم من القاموس
في بايثون فيه طريقتين للوصول لقيمة داخل dict، والفرق بينهم مهم فعلاً:
اختر حسب نيّتك من الكود:
- استخدم
[]لمّا يكون المفتاح لازم يكون موجود. لو مش موجود، ده معناه في باگ، وأنت عايز الخطأ يطلع بصوت عالي. - استخدم
.get()لمّا يكون "غير موجود" حالة طبيعية ومقبولة. كده تقدر تكتب قيم افتراضية من غير ما تلجأ لـ try/except.
إضافة وتحديث وحذف العناصر في قاموس بايثون
لمّا تسنِد قيمة لمفتاح، القاموس إمّا بينشئ المفتاح ده أو بيحدّث قيمته:
update() تدمج قاموسًا آخر أو أي iterable من الأزواج داخل القاموس:
المفاتيح المشتركة في overrides تطغى على نظيراتها في settings.
التحقق من وجود مفتاح في القاموس
عامل in يبحث في المفاتيح فقط، وليس في القيم:
للتحقق من القيم تحديدًا، استخدم user.values():
كيف تمر على عناصر قاموس بايثون
في بايثون، يوفّر لك القاموس (dict) ثلاث طرق أساسية للتكرار على محتوياته:
.items() هي الأداة التي ستلجأ إليها في أغلب الأحيان — تعطيك الزوج (المفتاح والقيمة) جاهزاً ومفكوكاً للاستخدام مباشرة.
ترتيب التكرار في إصدارات بايثون الحديثة (3.7 فما فوق) يتبع ترتيب الإضافة. القاموس ليس "صندوقاً عشوائياً" — إذا أضفت a ثم b ثم c، فستحصل عليها بنفس الترتيب عند التكرار. هذا ضمان صريح من اللغة يمكنك الاعتماد عليه.
كيفية ترتيب القاموس في بايثون
بما أن القواميس تحتفظ بترتيب الإضافة، فإن "ترتيب القاموس" يعني عملياً بناء قاموس جديد تُدرَج مفاتيحه بالترتيب الذي تريده:
تُرجع sorted() قائمة من الأزواج (tuples)، وعند تمريرها إلى dict(...) تحصل على قاموس جديد بالترتيب الذي تريده. أما إذا كنت تحتاج الأزواج المرتّبة فقط دون تحويلها إلى قاموس، فاستغنِ عن استدعاء dict() الخارجي.
دمج قواميس بايثون
بدءًا من Python 3.9، أصبح بإمكانك استخدام المعامل | مباشرةً:
عند تعارض المفاتيح، تفوز القيم الموجودة في القاموس الثاني (الذي يأتي بعد). أما .update() فهي تؤدي نفس الغرض لكن تعدّل القاموس الأصلي مباشرةً دون إنشاء قاموس جديد. وإذا كنت تستخدم إصدارات أقدم من بايثون، يمكنك اللجوء إلى {**defaults, **overrides} لدمج قواميس بايثون.
نمط setdefault
من الحالات الشائعة جداً: «إذا كان المفتاح موجوداً فخذ قيمته، وإن لم يكن موجوداً فاضبط له قيمة افتراضية ثم استخدمها».
أو الأفضل من ذلك، استخدم collections.Counter:
Counter هو صنف فرعي من dict مخصّص للعدّ بشكل افتراضي، وهو الخيار الأمثل كلما احتجت إلى حساب عدد مرات تكرار العناصر.
dict comprehension في بايثون
تشبه إلى حدٍّ كبير list comprehensions، لكنها تُستخدم لبناء القواميس:
نفس قواعد list comprehensions، لكن مع key: value داخل الأقواس المعقوفة.
القاموس كتوأم لـ JSON
قواميس بايثون تتطابق تقريبًا مع كائنات JSON، والتحويل بينهما يتم باستدعاء واحد فقط:
ولهذا السبب بالذات تجد القواميس في كل زاوية من زوايا الويب — طلبات وردود الـ API في النهاية ليست سوى تلاعب بقواميس بايثون مع قليل من الشبكة في الوسط.
مثال عملي على dict في بايثون
برنامج صغير يشبه ملف الإعدادات، مهمته تتبّع بيانات ملف شخصي لمستخدم:
القواميس المتداخلة، القيم القابلة للتعديل، و .get() مع قيمة افتراضية — هذه هي العُدّة الأساسية للتعامل مع أي بيانات على شكل سجلات.
لننتقل إلى الأمام
القوائم، الـ tuples، المجموعات، والقواميس. بهذه الأنواع الأربعة من المجموعات، تستطيع تمثيل معظم البيانات التي ستصادفها في بداياتك. في الدرس القادم سنتعرّف على الـ list comprehension — الطريقة المختصرة في بايثون لتحويل مجموعة إلى أخرى.
الأسئلة الشائعة
ما هو القاموس (dictionary) في بايثون؟
القاموس مجموعة من الأزواج على شكل مفتاح-قيمة. تصل إلى القيمة عبر مفتاحها، مثل prices['apple'] بدلاً من prices[0]. القواميس سريعة جداً في القراءة والكتابة، والمفاتيح يجب أن تكون فريدة، كما أنها تحافظ على ترتيب الإدراج في إصدارات بايثون الحديثة.
كيف أضيف مفتاحاً جديداً إلى قاموس في بايثون؟
ببساطة عبر الإسناد: my_dict['new_key'] = 'new value'. إذا كان المفتاح موجوداً مسبقاً فسيتم استبدال قيمته، وإذا لم يكن موجوداً فسيُضاف. لا يوجد فرق بين "الإدراج" و"التحديث" — الصيغة واحدة في كلتا الحالتين.
ما الفرق بين dict[key] و dict.get(key)؟
الصيغة dict[key] ترفع خطأ KeyError إذا لم يكن المفتاح موجوداً، أما dict.get(key) فترجع None (أو قيمة افتراضية تحددها أنت) بدلاً من ذلك. استخدم .get() عندما يكون غياب المفتاح أمراً متوقعاً وطبيعياً، واستخدم [key] عندما يكون غياب المفتاح يعني وجود خطأ برمجي.