تكرار السؤال: …
الإجابة المختصرة
لأن القيمة الافتراضية تُقيّم مرة واحدة فقط عند تعريف الدالة، فتشترك كل الاستدعاءات في نفس القائمة وتتراكم فيها البيانات.
الشرح
يُخزن الكائن الافتراضي في __defaults__ الخاصة بالدالة. إذا عدّلته داخل الدالة يبقى التعديل للاستدعاء التالي. الحل المعتاد استخدام None كقيمة افتراضية ثم إنشاء القائمة داخل الدالة. نفس المشكلة تحدث مع dict و set وأي كائن قابل للتغيير، ومع القيم المحسوبة مثل datetime.now() التي تُثبَّت لحظة التعريف.
مثال بالكود
def add_tag(tag, tags=[]): # خطأ
tags.append(tag)
return tags
add_tag("a") # ['a']
add_tag("b") # ['a', 'b'] !
def add_tag_fixed(tag, tags=None):
if tags is None:
tags = []
tags.append(tag)
return tagsأخطاء شائعة
- استخدام def f(created=datetime.now()) وتوقع وقت الاستدعاء بدل وقت التعريف.
- كتابة tags = tags or [] مما يستبدل القائمة الفارغة التي مررها المستدعي عمدًا.