القاموس (dict) في Python بنية بيانات تربط المفاتيح القابلة للتجزئة بـ_القيم_، ويُعرف في لغات البرمجة الأخرى باسم جدول التجزئة القابل لتغيير حجمه، أو خريطة التجزئة، أو المصفوفة الترابطية. والقواميس هي نوع الربط المدمج الوحيد في Python.
يجب أن تكون Keys قابلة للتجزئة وفريدة في القاموس كله.
يمكن أن تشمل أنواع المفاتيح numbers أو str أو tuples (من قيم غير قابلة للتغيير).
ولا يمكنها أن تحتوي على بنى بيانات قابلة للتغيير مثل lists أو dicts أو sets.
وبدءًا من Python 3.7، أصبح ترتيب مفاتيح dict مضمونًا ليطابق ترتيب إدخال العناصر.
ويمكن أن تكون values من أي نوع أو بنية بيانات.
كما يمكن للقيم أن تتداخل بشكل تعسفي، بحيث تشمل قوائم داخل قوائم، وقواميس فرعية، وبنى بيانات أخرى مخصصة أو مركّبة.
عند إعطاء key، تستطيع القواميس استرجاع value في زمن ثابت (في المتوسط) (بغض النظر عن عدد العناصر).
وبالمقارنة مع البحث عن قيمة داخل list أو array (دون معرفة موضع index)، يستهلك dict ذاكرة أكبر بكثير، لكن استرجاعه سريع جدًا.
وتكون القواميس مفيدة بشكل خاص حين تكون مجموعة العناصر كبيرة ويلزم الوصول إليها وتحديثها بشكل متكرر.
يمكن إنشاء القواميس بطرق كثيرة.
وأبسط طريقتين هما استخدام المنشئ dict() أو الإعلان عن dict حرفي.
dict()
يمكن استخدام dict() (منشئ صنف القاموس) مع أي كائن قابل للتكرار من أزواج key وvalue، أو مع سلسلة من الوسائط <name>=<value>:
#Passing a list of key,value tuples.
>>> wombat = dict([('name', 'Wombat'),('speed', 23),('land_animal', True)])
{'name': 'Wombat', 'speed': 23, 'land_animal': True}
#Using key=value arguments.
>>> bear = dict(name="Black Bear", speed=40, land_animal=True)
{'name': 'Black Bear', 'speed': 40, 'land_animal': True}
يمكن أيضًا كتابة dict مباشرةً على هيئة قاموس حرفي، باستخدام الأقواس المعقوفة ({}) التي تُحيط بأزواج key : value:
>>> whale = {"name": "Blue Whale", "speed": 35, "land_animal": False}
{'name': 'Blue Whale', 'speed': 35, 'land_animal': False}
يمكنك الوصول إلى عنصر في القاموس باستخدام مفتاح بين الأقواس المربعة ([]).
وإذا لم يكن key موجودًا في dict، يُرفع KeyError:
>>> bear["speed"]
40
>>> bear["color"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'color'
يمكن تجنّب KeyError بالوصول إلى عنصر عبر الطريقة .get(<key>, <default value>):
>>> bear.get("color", 'not found')
'not found'
يمكنك تغيير value الخاص بعنصر عبر الإسناد إلى المفتاح الخاص به:
#Assigning the value "Grizzly Bear" to the name key.
>>> bear["name"] = "Grizzly Bear"
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True}
>>> whale["speed"] = 25
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False}
ويمكن إضافة أزواج key:value جديدة بالطريقة نفسها:
# Adding a new "color" key with a new "tawney" value.
>>> bear["color"] = 'tawney'
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True, 'color': 'tawney'}
>>> whale["blowholes"] = 1
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False, 'blowholes': 1}
يمكنك استخدام الطريقة .pop(<key>) لحذف عنصر من القاموس.
وتزيل .pop() الزوج (key, value) وتُرجع value للاستخدام.
ومثل .get()، تقبل .pop(<key>) وسيطًا ثانيًا (dict.pop(<key>, <default value>)) يُرجع إذا لم يُعثر على key.
وهذا يمنع رفع KeyError:
#Using .pop() removes both the key and value, returning the value.
>>> bear.pop("name")
'Grizzly Bear'
#The "name" key is now removed from the dictionary.
#Attempting .pop() a second time will throw a KeyError.
>>> bear.pop("name")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'name'
#Using a default argument with .pop() will prevent a KeyError from a missing key.
>>> bear.pop("name", "Unknown")
'Unknown'
عند المرور على قاموس باستخدام for item in dict أو while item، سيتم التكرار على المفاتيح فقط بشكل افتراضي.
ويمكنك الوصول إلى القيم داخل الحلقة نفسها باستخدام الأقواس المربعة:
>>> for key in bear:
>>> print((key, bear[key])) #this forms a tuple of (key, value) and prints it.
('name', 'Black Bear')
('speed', 40)
('land_animal', True)
يمكنك أيضًا استخدام الطريقة .items()، التي تُرجع تلقائيًا صفوفًا من (key, value):
#dict.items() forms (key, value tuples) that can be unpacked and iterated over.
>>> for key, value in whale.items():
>>> print(key, ":", value)
name : Blue Whale
speed : 25
land_animal : False
blowholes : 1
وبالمثل، ستُرجع الطريقة .keys() المفاتيح keys، وستُرجع الطريقة .values() القيم values.
في هذا التمرين، ستُدير نظام مخزون.
ينبغي تنظيم المخزون حسب اسم العنصر، وينبغي أن يتتبّع عدد العناصر المتاحة.
سيكون عليك التعامل مع إضافة عناصر إلى المخزون.
في كل مرة يظهر فيها عنصر في قائمة معيّنة، ينبغي زيادة كمية العنصر بمقدار 1 في المخزون.
سيكون عليك أيضًا التعامل مع حذف العناصر من المخزون بإنقاص الكميات بمقدار 1 عند الطلب.
وأخيرًا، ستحتاج إلى تنفيذ دالة تُرجع جميع أزواج المفتاح والقيمة في مخزون معيّن على هيئة list من tuples.
نفّذ الدالة create_inventory(<input list>) التي تُنشئ «مخزونًا» من قائمة عناصر مُدخلة.
ينبغي أن تُرجع dict يحتوي على اسم كل عنصر مقترنًا بكميته المقابلة.
>>> create_inventory(["coal", "wood", "wood", "diamond", "diamond", "diamond"])
{"coal":1, "wood":2, "diamond":3}
نفّذ الدالة add_items(<inventory dict>, <item list>) التي تضيف قائمة من العناصر إلى المخزون المُمرَّر:
>>> add_items({"coal":1}, ["wood", "iron", "coal", "wood"])
{"coal":2, "wood":2, "iron":1}
نفّذ الدالة decrement_items(<inventory dict>, <items list>) التي تأخذ list من العناصر.
ينبغي أن تطرح دالتك 1 من عدد العنصر في كل مرة يظهر فيها ذلك العنصر في list:
>>> decrement_items({"coal":3, "diamond":1, "iron":5}, ["diamond", "coal", "iron", "iron"])
{"coal":2, "diamond":0, "iron":3}
لا ينبغي السماح لعدد العناصر في المخزون بالنزول دون 0.
إذا تجاوز عدد مرات ظهور عنصر في list المُدخلة العدد المتاح، ينبغي أن تبقى الكمية المسجّلة لذلك العنصر عند 0.
وتُتجاهل الطلبات الإضافية لإنقاص العدد بمجرد أن يصل العدد إلى صفر.
>>> decrement_items({"coal":2, "wood":1, "diamond":2}, ["coal", "coal", "wood", "wood", "diamond"])
{"coal":0, "wood":0, "diamond":1}
نفّذ الدالة remove_item(<inventory dict>, <item>) التي تحذف عنصرًا وعدده بالكامل من المخزون:
>>> remove_item({"coal":2, "wood":1, "diamond":2}, "coal")
{"wood":1, "diamond":2}
إذا لم يُعثر على العنصر في المخزون، ينبغي أن تُرجع الدالة المخزون الأصلي دون تغيير.
>>> remove_item({"coal":2, "wood":1, "diamond":2}, "gold")
{"coal":2, "wood":1, "diamond":2}
نفّذ الدالة list_inventory(<inventory dict>) التي تأخذ مخزونًا وتُرجع قائمة من صفوف (item, quantity).
ينبغي أن تتضمن القائمة العناصر المتاحة فقط (أي التي كميتها أكبر من صفر):
>>> list_inventory({"coal":7, "wood":11, "diamond":2, "iron":7, "silver":0})
[('coal', 7), ('diamond', 2), ('iron', 7), ('wood', 11)]
سجّل في Exercism لتتعلّم وتتقن Python عبر 17 مفهومًا146 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.