المسارات
/
Python
Python
/
المنهج
/
طُرق القواميس
طُ

طُرق القواميس في Python

تمرينان

نبذة عن طُرق القواميس

يوفّر صنف dict في Python العديد من الطرق المفيدة للتعامل مع القواميس. وقد عُرِض بعضها في مفهوم dict. وسنتناول هنا بعضها الآخر، إلى جانب بعض التقنيات للتكرار عبر القواميس والتعامل معها.

  • تُضيف <dict>.setdefault() المفاتيح تلقائيًا دون رفع KeyError.
  • تُنشئ <dict>.fromkeys(<iterable>, <default value>) قاموسًا جديدًا من أي عدد من الكائنات القابلة للتكرار.
  • توفّر <dict>.keys() و<dict>.values() و<dict>.items() مكرِّرات مريحة.
  • يمكن لـsorted(<dict>.items()) إعادة ترتيب مدخلات القاموس بسهولة.
  • تُحدِّث <dict_one>.update(<dict_two>) قاموسًا واحدًا بقيم متداخلة من قاموس آخر.
  • يدمج <dict> | <other_dict> و<dict> |= <other_dict> قاموسين أو يحدّثهما عبر العوامل.
  • تُنتج reversed(<dict>.keys()) وreversed(<dict>.values()) وreversed(<dict>.items()) عروضًا معكوسة.
  • تُزيل <dict>.popitem() زوجًا من (key، value) وتُرجعه.

استخدام setdefault() للإدراج دون أخطاء

تناول مفهوم القاموس سابقًا أن <dict>.get(<key>, <default value>) تُرجع قيمة value موجودة، أو default value إذا لم يُعثر على key في القاموس، وبذلك نتجنّب KeyError. وهذا مفيد في الحالات التي تفضّل فيها عدم إضافة معالجة أخطاء إضافية، لكنك لا تثق في وجود key تبحث عنه.

وللقيام بعملية إدراج "آمنة" مشابهة (دون KeyError)، تتوفّر طريقة <dict>.setdefault(<key>, <default value>). ستُرجع <dict>.setdefault(<key>, <default value>) قيمة value إذا وُجد key في القاموس. وإذا لم يُعثر على المفتاح، فإنها ستُدرج الزوج (key، default value) وتُرجع default value للاستخدام.

>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'}

# Looking for the value associated with key "Rock Brown".The key does not exist, 
# so it is added with the default value, and the value is returned.
>>> palette.setdefault('Rock Brown', '#694605')
'#694605'

# The (key, default value) pair has now been added to the dictionary.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'}

استخدام fromkeys() لملء قاموس من كائن قابل للتكرار

لملء قاموس سريعًا بمجموعة متنوعة من keys والقيم الافتراضية، فإن الطريقة الصنفية fromkeys(<iterable>, <default value>) ستُكرِّر عبر كائن قابل للتكرار من keys وتنشئ قاموسًا جديدًا. وستُضبط جميع values على default value المقدّمة:

>>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here')

{'Grassy Green': 'fill in hex color here',
 'Purple Mountains Majesty': 'fill in hex color here',
 'Misty Mountain Pink': 'fill in hex color here'}

إزالة زوج (مفتاح، قيمة) وإرجاعه باستخدام .popitem()

تُزيل .popitem() زوجًا واحدًا (key، value) من القاموس وتُرجعه. وتُرجَع الأزواج بترتيب آخر ما يدخل أول ما يخرج (LIFO). وإذا كان القاموس فارغًا، فسيؤدي استدعاء popitem() إلى رفع KeyError:

>>> palette_I = {'Grassy Green': '#9bc400', 
                 'Purple Mountains Majesty': '#8076a3', 
                 'Misty Mountain Pink': '#f9c5bd'}
>>> palette_I.popitem()
('Misty Mountain Pink', '#f9c5bd')

>>> palette_I.popitem()
('Purple Mountains Majesty', '#8076a3')

>>> palette_I.popitem()
('Grassy Green', '#9bc400')

# All (key, value) pairs have been removed.
>>> palette_I.popitem()
Traceback (most recent call last):
  line 1, in <module>
    palette_I.popitem()
KeyError: 'popitem(): dictionary is empty'

التكرار عبر مدخلات القاموس بواسطة العروض

تُرجع الطرق .keys() و.values() و.items() عروضًا قابلة للتكرار للقاموس.

ويمكن استخدام هذه العروض للتكرار بسهولة عبر المدخلات دون تغييرها. تكون العروض ديناميكية أيضًا: فعندما تتغيّر بيانات القاموس الأساسية، يعكس view object المرتبط هذا التغيير:

>>> palette_I = {'Grassy Green': '#9bc400', 
                 'Purple Mountains Majesty': '#8076a3', 
                 'Misty Mountain Pink': '#f9c5bd'}

# Using .keys() returns a list of keys.
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'])

# Using .values() returns a list of values.
>>> palette_I.values()
dict_values(['#9bc400', '#8076a3', '#f9c5bd'])

# Using .items() returns a list of (key, value) tuples.
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')])

# Views are dynamic.  Changing values in the dict 
# changes all of the associated views.
>>> palette_I['Purple Mountains Majesty'] = (128, 118, 163)
>>> palette_I['Deep Red'] = '#932432'

>>> palette_I.values()
dict_values(['#9bc400', (128, 118, 163), '#f9c5bd', '#932432'])

>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'Deep Red'])

>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')])

المزيد عن .keys() و.values() و.items()

في Python 3.7+، تحافظ dicts على ترتيب إدراج المدخلات، ما يتيح التكرار بنمط أول ما يدخل أول ما يخرج (FIFO) عند استخدام .keys() أو .values() أو .items().

وفي Python 3.8+، أصبحت العروض قابلة للعكس أيضًا. وهذا يتيح التكرار عبر المفاتيح أو القيم أو أزواج (key، value) بترتيب آخر ما يدخل أول ما يخرج (LIFO) باستخدام reversed(<dict>.keys()) أو reversed(<dict>.values()) أو reversed(<dict>.items()):

>>> palette_II = {'Factory Stone Purple': '#7c677f', 
                  'Green Treeline': '#478559', 
                  'Purple baseline': '#161748'}
>>> for item in palette_II.items():
...     print(item)
...
('Factory Stone Purple', '#7c677f')
('Green Treeline', '#478559')
('Purple baseline', '#161748')

>>> for item in reversed(palette_II.items()):
...     print(item)
...
('Purple baseline', '#161748')
('Green Treeline', '#478559')
('Factory Stone Purple', '#7c677f')

دمج القواميس باستخدام .update()

يمكن استخدام <dict_one>.update(<dict_two>) لدمج قاموسين. ستأخذ هذه الطريقة أزواج (key,value) من <dict_two> وتكتبها في <dict_one>:

>>> palette_I = {'Grassy Green': '#9bc400',
                 'Purple Mountains Majesty': '#8076a3',
                  'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
                  'Green Treeline': '#478559',
                  'Purple Baseline': '#161748'}

>>> palette_I.update(palette_II)

# Note that new items from palette_II are added.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'}

وعندما تتقاطع مفاتيح القاموسين، ستُستبدل قيمة value في dict_one بالقيمة المناظرة من dict_two:

>>> palette_I = {'Grassy Green': '#9bc400', 
                 'Purple Mountains Majesty': '#8076a3', 
                 'Misty Mountain Pink': '#f9c5bd', 
                 'Factory Stone Purple': '#7c677f', 
                 'Green Treeline': '#478559', 
                 'Purple baseline': '#161748'}
                   
>>> palette_III = {'Grassy Green': (155, 196, 0), 
                   'Purple Mountains Majesty': (128, 118, 163),
                   'Misty Mountain Pink': (249, 197, 189)}
>>> palette_I.update(palette_III)

# Overlapping values in palette_I are replaced with 
# values from palette_III
>>> palette_I
{'Grassy Green': (155, 196, 0),
  'Purple Mountains Majesty': (128, 118, 163), 
  'Misty Mountain Pink': (249, 197, 189), 
  'Factory Stone Purple': '#7c677f', 
  'Green Treeline': '#478559', 'Purple baseline': '#161748'}

دمج القواميس أو تحديثها باستخدام عاملي الاتحاد (| و|=)

يقدّم Python 3.9 وسيلة مختلفة لدمج القواميس dicts: عاملي union. سيُنشئ dict_one | dict_two قاموسًا جديدًا يتكوّن من أزواج (key، value) في dict_one وdict_two. وعندما يشترك القاموسان في مفاتيح، تكون الأولوية لقيم dict_two.

>>> palette_I = {'Grassy Green': '#9bc400', 
                 'Purple Mountains Majesty': '#8076a3', 
                 'Misty Mountain Pink': '#f9c5bd'}

>>> palette_II = {'Factory Stone Purple': '#7c677f', 
                  'Green Treeline': '#478559', 
                  'Purple baseline': '#161748'}

>>> new_dict = palette_I | palette_II
>>> new_dict
...
{'Grassy Green': '#9bc400',
 'Purple Mountains Majesty': '#8076a3',
 'Misty Mountain Pink': '#f9c5bd',
 'Factory Stone Purple': '#7c677f',
 'Green Treeline': '#478559',
 'Purple baseline': '#161748'}

يتصرّف dict_one |= other على نحو مشابه لـ<dict_one>.update(<other>)، لكن في هذه الحالة يمكن أن يكون other إمّا dict أو كائنًا قابلًا للتكرار من أزواج (key، value):

>>> palette_III = {'Grassy Green': (155, 196, 0),
                   'Purple Mountains Majesty': (128, 118, 163),
                   'Misty Mountain Pink': (249, 197, 189)}
>>> new_dict |= palette_III
>>> new_dict
...
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}

ترتيب القاموس

لا تمتلك القواميس طريقة ترتيب مدمجة. ومع ذلك، يمكن ترتيب عرض dict باستخدام الدالة المدمجة sorted() مع .items(). ويمكن بعد ذلك استخدام العرض المرتّب لإنشاء قاموس جديد. وما لم يُحدَّد مفتاح ترتيب، فالترتيب الافتراضي يكون حسب keys القاموس.

# Default ordering for a dictionary is last in, first out (LIFO).
>>> color_palette = {'Grassy Green': '#9bc400', 
                    'Purple Mountains Majesty': '#8076a3', 
                    'Misty Mountain Pink': '#f9c5bd', 
                    'Factory Stone Purple': '#7c677f', 
                    'Green Treeline': '#478559', 
                    'Purple baseline': '#161748'}
 
 
# The default sort order for a dictionary uses the keys.
>>> sorted_palette = dict(sorted(color_palette.items()))
>>> sorted_palette
{'Factory Stone Purple': '#7c677f',
 'Grassy Green': '#9bc400',
 'Green Treeline': '#478559',
 'Misty Mountain Pink': '#f9c5bd',
 'Purple Mountains Majesty': '#8076a3',
 'Purple baseline': '#161748'}


# A sort key can be provided in the form
# of an anonymous function (lambda). 
>>> value_sorted_palette = dict(sorted(color_palette.items(), key=lambda color: color[1]))
>>> value_sorted_palette
{'Purple baseline': '#161748',
 'Green Treeline': '#478559',
 'Factory Stone Purple': '#7c677f',
 'Purple Mountains Majesty': '#8076a3',
 'Grassy Green': '#9bc400',
 'Misty Mountain Pink': '#f9c5bd'} 

تبديل مفاتيح القاموس وقيمه

يستلزم تبديل مفاتيح القاموس وقيمه بشكل موثوق بعض الجهد، لكن يمكن إنجازه عبر loop باستخدام dict.items() أو ضمن استيعاب قاموسي. ويفترض التبديل الآمن أن مفاتيح dict وقيمه كلاهما قابل للتجزئة.

color_reference = {'Purple Mountains Majesty': '#8076a3',
                   'Misty Mountain Pink': '#f9c5bd',
                   'Factory Stone Purple': '#7c677f',
                   'Green Treeline': '#478559',
                   'Purple baseline': '#161748'}

# Creating a new dictionary to hold the swapped entries.
>>> swapped_color_reference = {}

# Iterating through the dictionary, using values as keys.
>>> for key, value in color_reference.items():
...     swapped_color_reference[value] = key

>>> swapped_color_reference
{'#8076a3': 'Purple Mountains Majesty',
 '#f9c5bd': 'Misty Mountain Pink',
 '#7c677f': 'Factory Stone Purple',
 '#478559': 'Green Treeline',
 '#161748': 'Purple baseline'}

 
# A dictionary comprehension can also be used to swap entries.
>>> swapped = {value: key for key, value in
               color_reference.items()}
>>> swapped
{'#8076a3': 'Purple Mountains Majesty',
 '#f9c5bd': 'Misty Mountain Pink',
 '#7c677f': 'Factory Stone Purple',
 '#478559': 'Green Treeline',
 '#161748': 'Purple baseline'}

إذا لم تكن القيم المخزّنة في dict فريدة، تصبح هناك حاجة إلى فحوص إضافية قبل إجراء تبديل المفاتيح والقيم:

# Things become more complicated if there are duplicates in 
# potential key values.This dict is arranged by hex, RGB, and HSL
# keys, but values repeat.
>>> extended_colors = {'#8076a3': 'Purple Mountains Majesty',
                       (128, 118, 163): 'Purple Mountains Majesty',
                       (21, 28, 0, 36): 'Purple Mountains Majesty',
                       '#f9c5bd': 'Misty Mountain Pink',
                       (249, 197, 189): 'Misty Mountain Pink',
                       (0, 21, 24, 2): 'Misty Mountain Pink',
                       '#7c677f': 'Factory Stone Purple',
                       (124, 103, 127): 'Factory Stone Purple',
                       (2, 19, 0, 50): 'Factory Stone Purple',
                       '#478559': 'Green Treeline',
                       (71, 133, 89): 'Green Treeline',
                       (47, 0, 33, 48): 'Green Treeline'}
                                
# New empty dictionary for holding swapped entries.
>>> consolidated_colors = {}

# Iterating over (key, value) pairs using .items()
>>> for key, value in extended_color_reference.items():
...    if value in consolidated_colors: # <--Check if key has already been created.
...        consolidated_colors[value].append(key)
...    else:
...        consolidated_colors[value] = [key]  # <--Create a value list with the former key in it.

>>> consolidated_colors
{'Purple Mountains Majesty': ['#8076a3', (128, 118, 163), (21, 28, 0, 36)],
 'Misty Mountain Pink': ['#f9c5bd', (249, 197, 189), (0, 21, 24, 2)],
 'Factory Stone Purple': ['#7c677f', (124, 103, 127), (2, 19, 0, 50)],
 'Green Treeline': ['#478559', (71, 133, 89), (47, 0, 33, 48)]}  

للحصول على شرح مفصّل عن القواميس وطرق التعامل معها، يُعدّ الدرس التعليمي الرسمي ومرجع المكتبة الرسمي نقطتي بداية ممتازتين.

كما يقدّم Real Python وFinxter مقالات وافية جدًا عن قواميس Python.

لمزيد من التفاصيل حول الترتيب، راجع دليل الترتيب في وثائق Python.

تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم طُرق القواميس

التدريب مقفل

افتح 3 تمارين إضافية لممارسة طُرق القواميس