في الدروس السابقة، تعاملنا مع القوائم (Lists) لتخزين مجموعات من العناصر المتسلسلة، حيث يتم الوصول إلى كل عنصر باستخدام رقمه التسلسلي أو الفهرس (Index). هذه الطريقة ممتازة عندما يكون لديك بيانات مرتبة مثل قائمة بأسماء المنتجات أو درجات الطلاب. لكن ماذا لو كنت تريد تخزين بيانات مرتبطة ببعضها البعض بطريقة أكثر معنوية؟ ماذا لو أردت البحث عن بيانات مستخدم باستخدام اسمه أو بريده الإلكتروني بدلاً من البحث برقم الفهرس العشوائي؟ هنا يأتي دور القواميس أو الـ Dictionaries في لغة بايثون.
في هذا الدرس، ستتعلم كيف تستخدم القواميس لربط البيانات، وكيف تختلف عن القوائم التقليدية، ومتى تكون الخيار الأنسب لمشروعك البرمجي القادم، مع أمثلة عملية وحالات استخدام حقيقية.
ما هو القاموس (Dictionary) في بايثون؟
القاموس في بايثون هو هيكل بيانات (Data Structure) يُستخدم لتخزين البيانات على شكل أزواج مترابطة، يُعرف كل زوج باسم المفتاح والقيمة أو (Key-Value Pair). تماماً مثل القاموس الحقيقي، حيث تبحث عن كلمة معينة (المفتاح) لتجد معناها أو تعريفها (القيمة).
يتميز القاموس بعدة خصائص أساسية جعلته أحد أهم الأدوات في لغة بايثون:
- مرن وسريع البحث: يتم البحث داخل القواميس باستخدام المفاتيح مباشرة، مما يجعل عملية استرجاع البيانات سريعة جداً بغض النظر عن حجم القاموس، وذلك بفضل الاعتماد الداخلي على خوارزميات التجزئة (Hashing).
- قابل للتعديل (Mutable): يمكنك إضافة عناصر جديدة، أو تعديل القيم الموجودة، أو حذف مفاتيح بالكامل بعد إنشاء القاموس دون الحاجة لإعادة إنشائه من جديد.
- مفاتيح فريدة (Unique Keys): لا يمكن أن يتكرر المفتاح داخل نفس القاموس. إذا قمت بتعريف نفس المفتاح مرتين، فستقوم بايثون بتحديث قيمته تلقائياً إلى القيمة الأخيرة.
- أنواع بيانات متنوعة: يمكن أن تكون المفاتيح والقيم من أي نوع بيانات تقريباً؛ فالقيم قد تكون أرقاماً، أو نصوصاً، أو حتى قوائم أو قواميس أخرى متداخلة.
طريقة إنشاء القاموس والوصول إلى البيانات
يتم إنشاء القاموس في بايثون باستخدام الأقواس المعقوفة أو الأقواس المتعرجة {}، مع وضع نقطتين رأسيتين : تفصل بين المفتاح وقيمته، وفاصلة , بين كل زوج وآخر.
دعنا نرى مثالاً عملياً لإنشاء قاموس يمثل معلومات مستخدم معين:
user_profile = {
"username": "geeky_coder",
"age": 28,
"is_active": True,
"skills": ["Python", "Git", "HTML"]
}
print(user_profile)في هذا المثال، أنشأنا متغيراً باسم user_profile يحتوي على أربعة أزواج من المفاتيح والقيم. المفاتيح هنا هي نصوص username و age و is_active و skills، بينما القيم متنوعة وتشمل نصوصاً، وأرقاماً، وقيماً منطقية، وقائمة.
كيفية استرجاع القيم من القاموس
للوصول إلى قيمة معينة داخل القاموس، يمكنك استخدام المفتاح الخاص بها داخل أقواس مربعة []، تماماً مثل التعامل مع الفهارس في القوائم، ولكن هنا تضع اسم المفتاح صراحة:
user_profile = {
"username": "geeky_coder",
"age": 28,
"is_active": True,
"skills": ["Python", "Git", "HTML"]
}
print(user_profile["username"])
print(user_profile["skills"])عند تشغيل هذا الكود، ستكون النتيجة طباعة اسم المستخدم والقائمة المرتبطة بمفتاح المهارات.
ماذا لو حاولت الوصول إلى مفتاح غير موجود؟ ستعطيك بايثون خطأً يُعرف بـ KeyError. لتجنب هذا الخطأ، يُفضل استخدام الدالة المدمجة get():
# استخدام دالة get لتجنب الأخطاء
email = user_profile.get("email", "غير متوفر")
print(email)تقوم الدالة get() بالبحث عن المفتاح email، وإذا لم تجده، فإنها لا تسبب خطأً في البرنامج بل تعيد القيمة الافتراضية التي حددتها وهي "غير متوفر".
تعديل وإضافة وحذف البيانات في القواميس
واحدة من أكبر مزايا القواميس هي مرونتها العالية في التحديث المستمر للبيانات أثناء تشغيل البرنامج.
إضافة مفتاح جديد أو تعديل قيمة موجودة
إذا قمت بتعيين قيمة لمفتاح غير موجود، فسيقوم بايثون بإضافته تلقائياً. أما إذا كان المفتاح موجوداً مسبقاً، فسيتم تحديث قيمته:
# تعريف قاموس لمنتج في متجر
product = {
"name": "سماعات لاسلكية",
"price": 150,
"in_stock": True
}
# تعديل السعر
product["price"] = 135
# إضافة مفتاح جديد للتقييم
product["rating"] = 4.5
print(product)هنا تم تغيير السعر من 150 إلى 135، وتمت إضافة مفتاح جديد باسم rating بقيمة 4.5 بكل سهولة.
حذف العناصر من القاموس
لديك عدة طرق لحذف العناصر عند الحاجة. الطريقة الأكثر شيوعاً هي استخدام الكلمة المفتاحية del:
# حذف مفتاح معين
del product["in_stock"]
print(product)كما يمكنك استخدام دالة pop() إذا كنت ترغب في حذف المفتاح والاحتفاظ بقيمته في متغير لاستخدامها لاحقاً في البرنامج، أو استخدام popitem() لحذف آخر زوج تم إضافته.
# استخدام دالة pop للاحتفاظ بالقيمة المحذوفة
removed_price = product.pop("price")
print(f"تم حذف السعر وقيمته كانت: {removed_price}")
print(product)المرور على القواميس باستخدام الحلقات التكرارية (Loops)
غالباً ما ستتحتم عليك الإحاطة بقواميس تحتوي على بيانات ضخمة وتحتاج إلى تصفحها عن طريق الحلقات مثل for. تتيح لك بايثون طرقاً متعددة للوصول إلى المفاتيح، أو القيم، أو الاثنين معاً.
student_scores = {
"أحمد": 85,
"سارة": 92,
"خالد": 78
}
# المرور على المفاتيح والقيم معاً باستخدام items()
for name, score in student_scores.items():
print(f"الطالب {name} حصل على نتيجة {score}")في هذا المثال، استخدمنا الدالة items() التي تعيد لنا كل مفتاح وقيمته معاً في كل دورة من حلقات التكرار، مما يسهل عملية طباعة البيانات وتنسيقها بشكل مقروء للمستخدم.
يمكنك أيضاً استخدام keys() للمفاتيح فقط، أو values() للقيم وحدها إذا كنت بحاجة إلى إجراء حسابات على القيم مثل جمع الدرجات أو حساب المتوسط:
# استخراج القيم وحدها وحساب المجموع
scores = student_scores.values()
total_score = sum(scores)
print(f"مجموع الدرجات هو: {total_score}")حالة استخدام عملية: إدارة إعدادات التطبيق
تُعد القواميس ممتازة لتخزين إعدادات التطبيقات البرمجية (Configuration Settings)، حيث يمثل كل مفتاح اسم الإعداد وقيمته تمثل حالة التفعيل أو القيمة المطلوبة:
app_config = {
"host": "localhost",
"port": 8080,
"debug_mode": True,
"allowed_extensions": [".png", ".jpg", ".pdf"]
}
# التحقق من حالة وضع التصحيح
if app_config.get("debug_mode"):
print("التطبيق يعمل حالياً في وضع التطوير والتصحيح.")
else:
print("التطبيق يعمل في وضع الإنتاج.")أخطاء شائعة يقع فيها المبتدئون عند استخدام القواميس
عندما تبدأ في استخدام القواميس، قد تواجه بعض الأخطاء المتكررة التي يقع فيها معظم المبرمجين المبتدئين. معرفتها مسبقاً سيوفر عليك الكثير من وقت التصحيح:
- استخدام أنواع بيانات غير قابلة للتغيير كمفاتيح: يجب أن تكون مفاتيح القاموس من أنواع بيانات ثابتة (Immutable) مثل النصوص، الأرقام، أو القيم المنطقية. لا يمكنك استخدام القوائم (Lists) كمفاتيح لأنها قابلة للتعديل (Mutable) وسيؤدي ذلك إلى ظهور خطأ
TypeError. - الخلط بين الفهارس والأقواس: محاولة الوصول إلى عناصر القاموس باستخدام الأرقام التسلسلية مثل
user_profile[0]بدلاً من استخدام المفتاح النصي. القواميس لا تعتمد على الترتيب العددي في الوصول الأساسي للمفتاح (في الإصدارات الحديثة من بايثون يتم الحفاظ على ترتيب الإضافة، لكن الوصول يتم عبر المفتاح حصراً). - نسيان التحقق من وجود المفتاح: الاعتماد المطلق على وجود مفتاح معين دون التأكد منه، مما يتسبب في توقف البرنامج بشكل مفاجئ عند حدوث خطأ
KeyError، وهنا تبرز أهمية استخدام دالةget()أو عبارة التحققif key in dict.
# طريقة آمنة للتحقق من وجود المفتاح قبل استخدامه
if "age" in user_profile:
print(f"عمر المستخدم هو: {user_profile['age']}")
else:
print("مفتاح العمر غير موجود في البيانات.")مقارنة سريعة: القوائم (Lists) مقابل القواميس (Dictionaries)
من المفيد معرفة متى تستخدم القائمة ومتى تستخدم القاموس:
- القوائم (Lists): مناسبة جداً عندما يكون الترتيب مهماً، والبيانات متسلسلة، وتعتمد على الفهارس الرقمية (0, 1, 2...). مثال: قائمة المهام اليومية أو تسلسل خطوات المعالجة.
- القواميس (Dictionaries): مناسبة جداً عندما تريد ربط بيانات لها معاني دلالية بمفاتيح نصية أو رقمية فريدة، والوصول السريع بغض النظر عن الترتيب. مثال: ملف تعريف مستخدم، إعدادات نظام، أو جدول بيانات مترابط.
خلاصة
تُعد القواميس (Dictionaries) في لغة بايثون أداة لا غنى عنها لأي مبرمج، فهي تمثل العمود الفقري لتنظيم البيانات المعقدة وتمثيل الكائنات بطريقة تشبه الواقع البرمجي. من خلال ربط المفاتيح بقيمها، يمكنك بناء تطبيقات متكاملة تدير بيانات المستخدمين، أو إعدادات البرامج، أو منتجات المتاجر الإلكترونية بكل كفاءة وسرعة.
في الدروس القادمة، سنبني على هذه المعرفة لنرى كيف يمكن دمج القواميس مع القوائم لبناء هياكل بيانات أكثر تقدماً وقوة وقادرة على التعامل مع سيناريوهات برمجية واسعة النطاق.