التكرار على القواميس باستخدام حلقات "for"

سئل على ٢١ يوليو ٢٠١٠  ·  تمت مشاهدة 4.5M مرة  ·  مصدر

TopChef picture
في ٢١ يوليو ٢٠١٠

أنا في حيرة من الكود التالي:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    print key, 'corresponds to', d[key]

ما لا أفهمه هو الجزء key . كيف تدرك بايثون أنها تحتاج فقط إلى قراءة المفتاح من القاموس؟ هل key كلمة خاصة في Python؟ أم أنه مجرد متغير؟

الإجابات

sberry picture
في ٢١ يوليو ٢٠١٠
5632

key هو مجرد اسم متغير.

for key in d:

سوف يتكرر ببساطة فوق المفاتيح الموجودة في القاموس ، بدلاً من المفاتيح والقيم. للتكرار على كل من المفتاح والقيمة ، يمكنك استخدام ما يلي:

بالنسبة إلى Python 3.x:

for key, value in d.items():

بالنسبة إلى Python 2.x:

for key, value in d.iteritems():

للاختبار بنفسك ، قم بتغيير الكلمة key إلى poop .

في Python 3.x ، تم استبدال iteritems() بـ items() ببساطة ، والتي تُرجع عرضًا شبيهًا بالمجموعة مدعومًا من dict ، مثل iteritems() ولكن أفضل. هذا متاح أيضًا في 2.7 كـ viewitems() .

ستعمل العملية items() لكل من 2 و 3 ، ولكن في 2 ستعيد قائمة بأزواج القاموس (key, value) ، والتي لن تعكس التغييرات التي تحدث بعد items() call. إذا كنت تريد سلوك 2.x في 3.x ، فيمكنك استدعاء list(d.items()) .

ars picture
في ٢١ يوليو ٢٠١٠
466

ليس هذا المفتاح هو كلمة خاصة ، لكن القواميس تطبق بروتوكول المكرر. يمكنك القيام بذلك في صفك ، على سبيل المثال ، راجع هذا السؤال حول كيفية إنشاء مكررات الفصل.

في حالة القواميس ، يتم تنفيذه على المستوى C. التفاصيل متوفرة في PEP 234 . على وجه الخصوص ، القسم بعنوان "مكررات القاموس":

  • تقوم القواميس بتنفيذ فتحة tp_iter التي تقوم بإرجاع مكرر فعال يقوم بالتكرار فوق مفاتيح القاموس. [...] هذا يعني أنه يمكننا الكتابة

    for k in dict: ...
    

    وهو ما يعادل ، ولكنه أسرع بكثير من

    for k in dict.keys(): ...
    

    طالما لم يتم انتهاك القيود المفروضة على تعديلات القاموس (إما عن طريق الحلقة أو بواسطة مؤشر ترابط آخر).

  • أضف توابع إلى القواميس تُرجع أنواعًا مختلفة من التكرارات بشكل صريح:

    for key in dict.iterkeys(): ...
    
    for value in dict.itervalues(): ...
    
    for key, value in dict.iteritems(): ...
    

    هذا يعني أن for x in dict هو اختصار لـ for x in dict.iterkeys() .

في Python 3 ، لم يعد يتم دعم dict.iterkeys() و dict.itervalues() و dict.iteritems() . استخدم dict.keys() و dict.values() و dict.items() بدلاً من ذلك.

John La Rooy picture
في ٢١ يوليو ٢٠١٠
222

التكرار على dict يتكرر من خلال مفاتيحه بدون ترتيب معين ، كما ترى هنا:

تحرير: ( لم يعد هذا هو ليس سلوكًا

>>> d = {'x': 1, 'y': 2, 'z': 3} 
>>> list(d)
['y', 'x', 'z']
>>> d.keys()
['y', 'x', 'z']

بالنسبة لمثالك ، من الأفضل استخدام dict.items() :

>>> d.items()
[('y', 2), ('x', 1), ('z', 3)]

يمنحك هذا قائمة مجموعات. عندما تقوم بالتكرار فوقهم بهذه الطريقة ، يتم تفكيك كل مجموعة إلى k و v تلقائيًا:

for k,v in d.items():
    print(k, 'corresponds to', v)

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

for letter, number in d.items():
    print(letter, 'corresponds to', number)

من الجيد التعود على استخدام سلاسل التنسيق:

for letter, number in d.items():
    print('{0} corresponds to {1}'.format(letter, number))
ssoler picture
في ٢١ يوليو ٢٠١٠
94

key هو ببساطة متغير.

بالنسبة إلى Python2.x :

d = {'x': 1, 'y': 2, 'z': 3} 
for my_var in d:
    print my_var, 'corresponds to', d[my_var]

... أو أفضل ،

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.iteritems():
    print the_key, 'corresponds to', the_value

بالنسبة إلى Python3.x :

d = {'x': 1, 'y': 2, 'z': 3} 
for the_key, the_value in d.items():
    print(the_key, 'corresponds to', the_value)
Alexander Gessler picture
في ٢١ يوليو ٢٠١٠
67

عندما تقوم بالتكرار خلال القواميس باستخدام بناء الجملة for .. in .. ، فإنها تتكرر دائمًا عبر المفاتيح (يمكن الوصول إلى القيم باستخدام dictionary[key] ).

للتكرار على أزواج القيمة الرئيسية ، في Python 2 استخدم for k,v in s.iteritems() ، وفي Python 3 for k,v in s.items() .

chryss picture
في ٢١ يوليو ٢٠١٠
35

هذا هو مصطلح حلقات شائع جدا. in عامل تشغيل. لمعرفة وقت استخدام for key in dict وعندما يجب أن يكون for key in dict.keys() راجع مقالة Python الاصطلاحية لـ David Goodger (نسخة مؤرشفة) .

Aaron Hall picture
في ٢١ يونيو ٢٠١٧
23

التكرار على القواميس باستخدام حلقات "for"

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    ...

كيف تدرك بايثون أنها تحتاج فقط إلى قراءة المفتاح من القاموس؟ هل المفتاح كلمة خاصة في بايثون؟ أم أنه مجرد متغير؟

انها ليست مجرد حلقات for . الكلمة المهمة هنا هي "التكرار".

القاموس هو تعيين لمفاتيح القيم:

d = {'x': 1, 'y': 2, 'z': 3} 

في أي وقت نكرره ، نكرره على المفاتيح. الغرض من المتغير key هو أن يكون وصفيًا - وهو مناسب تمامًا لهذا الغرض.

يحدث هذا في قائمة الفهم:

>>> [k for k in d]
['x', 'y', 'z']

يحدث ذلك عندما نقوم بتمرير القاموس إلى القائمة (أو أي كائن من نوع المجموعة):

>>> list(d)
['x', 'y', 'z']

الطريقة التي تكرر بها Python ، في السياق الذي تحتاج إليه ، تستدعي طريقة __iter__ للكائن (في هذه الحالة القاموس) والتي ترجع مكررًا (في هذه الحالة ، كائن keyiterator):

>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>

لا يجب أن نستخدم هذه الطرق الخاصة بأنفسنا ، بدلاً من ذلك ، استخدم الوظيفة المضمنة ذات الصلة لاستدعائها ، iter :

>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>

التكرارات لها طريقة __next__ - لكننا نسميها بالدالة المضمنة ، next :

>>> next(key_iterator)
'x'
>>> next(key_iterator)
'y'
>>> next(key_iterator)
'z'
>>> next(key_iterator)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

عندما يتم استنفاد المكرر ، فإنه يرفع StopIteration . هذه هي الطريقة التي يعرف بها Python الخروج من حلقة for ، أو قائمة فهم ، أو تعبير منشئ ، أو أي سياق تكراري آخر. بمجرد أن يقوم المكرر بجمع StopIteration فإنه سيرفعه دائمًا - إذا كنت تريد التكرار مرة أخرى ، فأنت بحاجة إلى واحد جديد.

>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']

العودة إلى الاملاءات

لقد رأينا الإملاءات تتكرر في العديد من السياقات. ما رأيناه هو أنه في أي وقت نكرر فيه الأمر ، نحصل على المفاتيح. العودة إلى المثال الأصلي:

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:

إذا قمنا بتغيير اسم المتغير ، فإننا لا نزال نحصل على المفاتيح. دعنا نحاول:

>>> for each_key in d:
...     print(each_key, '=>', d[each_key])
... 
x => 1
y => 2
z => 3

إذا أردنا تكرار القيم ، فنحن بحاجة إلى استخدام طريقة الدكتات .values أو لكليهما معًا ، .items :

>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]

في المثال الموضح ، سيكون من الأفضل تكرار العناصر مثل هذا:

for a_key, corresponding_value in d.items():
    print(a_key, corresponding_value)

لكن للأغراض الأكاديمية ، فإن مثال السؤال جيد.

jdhao picture
في ٢٥ مايو ٢٠١٧
21

لدي حالة استخدام حيث يتعين عليّ تكرار الأمر للحصول على المفتاح وزوج القيمة وأيضًا المؤشر الذي يشير إلى مكاني. هكذا أفعل ذلك:

d = {'x': 1, 'y': 2, 'z': 3} 
for i, (key, value) in enumerate(d.items()):
   print(i, key, value)

لاحظ أن الأقواس حول المفتاح ، القيمة مهمة ، بدون الأقواس ، ستحصل على خطأ في القيمة "لا توجد قيم كافية لفك الضغط".

Ankur Agarwal picture
في ٣ نوفمبر ٢٠١٧
10

يمكنك التحقق من تطبيق CPython dicttype على GitHub. هذا هو توقيع الطريقة التي تنفذ الديكتاتور:

_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
             PyObject **pvalue, Py_hash_t *phash)

CPython Dictobject.c

Neil Chowdhury  o_O picture
في ٣١ ديسمبر ٢٠١٥
5

للتكرار على المفاتيح ، من الأفضل استخدام my_dict.keys() . إذا حاولت أن تفعل شيئًا كهذا:

for key in my_dict:
    my_dict[key+"-1"] = my_dict[key]-1

سيؤدي ذلك إلى حدوث خطأ في وقت التشغيل لأنك تقوم بتغيير المفاتيح أثناء تشغيل البرنامج. إذا كنت مضبوطًا تمامًا على تقليل الوقت ، فاستخدم طريقة for key in my_dict ، ولكن تم تحذيرك ؛).