یک «دیکشنری» (dict) در Python یک ساختار داده است که کلیدهای هشپذیر را به مقدارها نسبت میدهد و در زبانهای برنامهنویسی دیگر با نامهای یک جدول هش قابل تغییر اندازه، هشمپ یا آرایهی انجمنی شناخته میشود.
دیکشنریها تنها نوع نگاشت توکار Python هستند.
Keys باید هشپذیر و در سراسر دیکشنری یکتا باشند.
نوع کلیدها میتواند شامل numbers، str یا tuples (از مقدارهای تغییرناپذیر) باشد.
آنها نمیتوانند ساختارهای دادهی تغییرپذیر مانند lists، dicts یا sets را در خود جای دهند.
از Python ۳.۷ به بعد، ترتیب کلیدهای 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'
دسترسی به یک عنصر با متد .get(<key>, <default value>) میتواند از خطای KeyError جلوگیری کند:
>>> 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 از اقلام میگیرد. تابع شما باید برای هر بار که یک قلم در list ظاهر میشود، 1 را از تعداد آن قلم کم کند:
>>> 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)]