الفرق بين defaultdict وdict في بايثون

في بايثون، تعد القواميس واحدة من أكثر أنواع البيانات المضمنة مرونة. فهي رائعة لبناء البيانات ويمكن أن تساعدك في حل عدد لا يحصى من المشكلات. ولكن ماذا لو أخبرتك أن هناك إصدارًا أقوى من القواميس ربما لم تسمع به من قبل؟ نعم، أنا أتحدث عن نوع collections.defaultdict.

في هذه المقالة، سنستكشف ما هو defaultdict وكيف يختلف عن قاموس بايثون العادي (أو dict باختصار).

ما هو اdict؟

القاموس هو نوع بيانات مدمج في بايثون يخزن مجموعات قابلة للتغيير وغير مرتبة من أزواج القيمة والمفتاح. يقوم كل زوج قيمة ومفتاح في القاموس بربط المفتاح بالقيمة المرتبطة به، مما يجعل من السهل استرداد القيم لمفاتيح معينة.

student = {
    "name": "John Doe",
    "age": 20,
    "courses": ["Math", "Science"]
}

print(student["name"])
# Output: John Doe

في هذا الكود، المفاتيح هي “name” و”age” و”courses”، ولكل منها قيم مرتبطة بها. يمكنك الوصول إلى أي قيمة من خلال مفتاحها، كما فعلنا مع student["name"].

ولكن ماذا يحدث عندما تحاول الوصول إلى مفتاح غير موجود في القاموس؟ حسنًا، يطرح بايثون خطأ KeyError:

print(student["grade"])
# Output: KeyError: 'grade'

هذا هو أحد القيود التي تواجه القاموس العادي. فهو لا يتعامل جيدًا مع المفاتيح المفقودة. وفي التطبيقات الواقعية، قد يؤدي هذا إلى تعطل برنامجك إذا لم تكن حريصًا. وهنا يأتي دور defaultdicts، ولكننا سنتحدث عن ذلك لاحقًا في المقالة.

ملاحظة: يمكنك تجنب استثناءات KeyError في القواميس العادية باستخدام التابع get، والتي تعيد القيمة None إذا لم يتم العثور على المفتاح. ومع ذلك، لا يعد هذا مثاليًا دائمًا، وخاصةً عندما تريد توفير قيمة افتراضية بخلاف None.

ما هو defaultdict؟

defaultdict هو قاموس متخصص توفره وحدة collections في بايثون. إنه فئة فرعية من فئة dict المضمنة. إذن، ما الذي يجعله مميزًا للغاية؟ حسنًا، إنه لا يلقي خطأ KeyError عندما تحاول الوصول إلى مفاتيح غير موجودة بالفعل في القاموس أو تعديلها. بدلاً من ذلك، يقوم بتهيئته بعنصر من نوع البيانات الذي تمررها كحجة عند إنشاء defaultdict. يمكن أن يكون هذا مفيدًا للغاية عند العمل مع هياكل بيانات كبيرة.

دعونا نلقي نظرة سريعة على كيفية تهيئة defaultdict:

from collections import defaultdict

# Initializing with list as default_factory
dd = defaultdict(list)

في المثال أعلاه، إذا حاولت الوصول إلى مفتاح غير موجود، فسوف يقوم بايثون بإرجاع قائمة فارغة [] بدلاً من رمي KeyError.

print(dd["non_existent_key"])
# Output: []

الحجة التي تمررها أثناء تهيئة defaultdict تسمى default_factory. إنها دالة توفر القيمة الافتراضية للقاموس الذي تم إنشاؤه. إذا كانت هذه الحجة غائبة، فإن defaultdict يتصرف بشكل أساسي مثل القاموس العادي.

الاختلافات الرئيسية

الآن بعد أن فهمنا ما هو defaultdict، دعنا نلقي نظرة على الاختلافات الرئيسية بين defaultdict وقاموس بايثون النموذجي.

القيم الافتراضية: الفرق الأكثر أهمية، كما رأينا بالفعل، هو أن defaultdict يعين تلقائيًا قيمة افتراضية لمفتاح غير موجود. وهذا يختلف عن القاموس القياسي، الذي يثير خطأ KeyError عند محاولة الوصول إلى مفتاح غير موجود أو تعديله.

# Standard dict
d = {}
print(d["non_existent_key"])
# Output: KeyError: 'non_existent_key'

# Defaultdict
from collections import defaultdict
dd = defaultdict(int)
print(dd["non_existent_key"])
# Output: 0

التهيئة: أثناء تهيئة defaultdict، تحتاج إلى توفير دالة default_factory التي ستحدد القيمة الافتراضية للمفاتيح غير الموجودة. من ناحية أخرى، لا يتطلب أو يدعم القاموس القياسي هذه الدالة.

d = {}  # Standard dict
dd = defaultdict(list)  # Defaultdict

حالات الاستخدام: يعد defaultdict أكثر فائدة عند التعامل مع مجموعات بيانات كبيرة حيث تريد تجنب التعامل مع استثناءات KeyError. يُستخدم عادةً في عمليات التجميع أو العد أو التراكم.

متى تستخدم defaultdict مقابل dict

بالطبع، يعتمد الاختيار بين defaultdict وdict على احتياجاتك المحددة. إذا كنت تتعامل مع موقف حيث تريد تجنب أخطاء المفاتيح وتعرف مسبقًا نوع القيمة الافتراضية التي تريدها للمفاتيح غير الموجودة، فإن defaultdict هو الحل.

لنفترض أنك تقوم ببناء قاموس لحساب تكرار الكلمات في نص ما. باستخدام القاموس العادي، يتعين عليك التحقق مما إذا كانت الكلمة مفتاحًا بالفعل في القاموس قبل زيادة عددها. باستخدام defaultdict، يمكنك ببساطة تعيين نوع القيمة الافتراضية على أنه int وزيادة العدد دون أي فحوصات.

من ناحية أخرى، إذا كنت تريد أن يقوم برنامجك بإلقاء خطأ عند الوصول إلى مفتاح غير موجود، أو إذا لم يكن لديك قيمة افتراضية واضحة، فقد يكون القاموس العادي أكثر ملاءمة.

كيفية استخدام defaultdict

إن استخدام defaultdict بسيط للغاية. تبدأ باستيراده من وحدة collections. ثم عندما تقوم بإنشاء defaultdict، فإنك تمرر النوع الافتراضي للقاموس. قد يكون هذا النوع int أو list أو set أو dict أو حتى دالة محددة من قبل المستخدم.

دعنا نلقي نظرة على مثال. لنفترض أننا نريد إنشاء قاموس لتخزين درجات الطلاب في مواد مختلفة. يمكننا استخدام defaultdict مع قائمة كنوع افتراضي:

from collections import defaultdict

# Create a defaultdict with list as the default type
grades = defaultdict(list)

# Add grades
grades['Math'].append(85)
grades['English'].append(90)

print(grades)

عندما تقوم بتشغيل هذا الكود، سوف تحصل على الناتج التالي:

defaultdict(<class 'list'>, {'Math': [85], 'English': [90]})

كما ترى، لم يكن علينا التحقق مما إذا كانت “الرياضيات” أو “اللغة الإنجليزية” من المفاتيح الموجودة بالفعل في القاموس. لقد تمكنا من إضافة الدرجات مباشرة. إذا حاولنا الوصول إلى الدرجات الخاصة بموضوع لم يتم إضافته بعد، فسنحصل على قائمة فارغة بدلاً من خطأ المفتاح:

print(grades['Science'])

سيؤدي هذا إلى:

[]

ملاحظة: تذكر أن النوع الافتراضي الذي تمرر إلى defaultdict هو دالة، وليس قيمة. لذا، يجب عليك تمرير list بدلاً من []، أو int بدلاً من 0.

كيفية استخدام القاموس

قاموس بايثون هو نوع بيانات مضمّن يستخدم لتخزين البيانات في أزواج مفتاح-قيمة. فيما يلي مثال بسيط لكيفية استخدامه:

# Creating a dictionary
my_dict = {'name': 'John', 'age': 30}

# Accessing a value
print(my_dict['name'])  # Output: John

# Updating a value
my_dict['age'] = 31
print(my_dict['age'])  # Output: 31

# Adding a new key-value pair
my_dict['job'] = 'Engineer'
print(my_dict)  # Output: {'name': 'John', 'age': 31, 'job': 'Engineer'}

أحد الأشياء التي يجب تذكرها عند استخدام dict هو أنه سيثير KeyError إذا حاولت الوصول إلى مفتاح غير موجود:

print(my_dict['hobby'])  # Raises KeyError: 'hobby'

في هذه المقالة، قمنا بالتعمق أكثر في عالم قواميس بايثون، مع التركيز بشكل خاص على النوعين dict وcollections.defaultdict. لقد استكشفنا الاختلافات الرئيسية بينهما، مثل كيفية توفير defaultdict لقيمة افتراضية للمفاتيح غير الموجودة، وبالتالي تجنب استثناءات KeyError. لقد نظرنا أيضًا في حالات الاستخدام الخاصة بهما، حيث يكون dict أفضل للسيناريوهات التي تحتاج فيها إلى التحكم الصارم في المفاتيح الموجودة في القاموس الخاص بك، ويكون defaultdict أكثر فائدة عندما تتعامل مع مجموعات بيانات كبيرة وتحتاج إلى تجنب عمليات التحقق المستمرة من وجود المفاتيح.


اكتشاف المزيد من بايثون العربي

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

Scroll to Top

اكتشاف المزيد من بايثون العربي

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

Continue reading