دی

دیکشنری در Python

37 تمرین

درباره‌ی دیکشنری

دیکشنری (dict) در پایتون یک ساختار داده است که _کلید_های هش‌پذیر را به مقدارها نسبت می‌دهد و در زبان‌های برنامه‌نویسی دیگر با نام‌های جدول هش با اندازه‌ی قابل تغییر، هش‌مپ یا آرایه‌ی انجمنی شناخته می‌شود. دیکشنری تنها نوع نگاشت توکار پایتون است.

keys باید هش‌پذیر و در سراسر دیکشنری یکتا باشد. نوع کلیدها می‌تواند number، str یا tuple (از مقادیر تغییرناپذیر) باشد. آن‌ها نمی‌توانند ساختارهای داده‌ی تغییرپذیر مانند list، dict یا set داشته باشند. از پایتون ۳.۷ به بعد، ترتیب کلیدهای dict تضمین‌شده همان ترتیبی است که مدخل‌ها درج می‌شوند.

values می‌تواند از هر نوع یا ساختار داده باشد. مقدارها همچنین می‌توانند به‌صورت دلخواه تودرتو شوند، پس می‌توانند شامل لیست‌هایی از لیست‌ها، زیردیکشنری‌ها و دیگر ساختارهای داده‌ی سفارشی یا مرکب باشند.

با داشتن یک key، دیکشنری می‌تواند یک value را (به‌طور میانگین) در زمان ثابت (مستقل از تعداد مدخل‌ها) بازیابی کند. در مقایسه با جست‌وجوی یک مقدار درون یک list یا array (بدون دانستن موقعیت index)، یک dict حافظه‌ی بسیار بیشتری مصرف می‌کند، اما بازیابی آن خیلی سریع است.

دیکشنری به‌ویژه در موقعیت‌هایی مفید است که مجموعه‌ی عناصر بزرگ باشد و باید مکرراً به آن دسترسی پیدا کرد و به‌روزرسانی کرد.

ساختن دیکشنری

دیکشنری را می‌توان به روش‌های مختلفی ساخت، از جمله:

  • با استفاده از متد کلاس fromkeys().
  • با استفاده از درک دیکشنری.
  • ادغام دو دیکشنری از طریق بازکردن (**).
  • ادغام دیکشنری‌ها با عملگر | (به‌روزرسانی).
  • استفاده از یک حلقه برای افزودن تدریجی مدخل‌ها به یک 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}

>>> wombat = {'name': 'Wombat',
              'speed': 23,
              'land_animal': True,
              'color': 'Brindle'}

>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True, 'color': 'Brindle'}

دیکشنری تودرتو

دیکشنری را می‌توان به‌صورت دلخواه تودرتو کرد:

animals = {
    "Real" : {
        "Winged" : {
            "Sparrow" : {'name': 'sparrow','speed': 12, 'land_animal': True},
            "Kestrel" : {'name': 'kestrel', 'speed': 15, 'land_animal': True}
           },
        "Legged" : {
            "Wombat" : {'name': 'Wombat', 'speed': 23, 'land_animal': True},
            "Black Bear": {'name': 'Black Bear', 'speed': 40, 'land_animal': True},
            "Polecat" : {'name': 'Polecat', 'speed': 15, 'land_animal': True}
           },
        "Other" :  {
            "Whale" : {'name': 'Blue Whale', 'speed': 35, 'land_animal': False},
            "Orca" : {'name': 'Orca', 'speed': 45, 'land_animal': False},
            "Snake" : {'name': 'Python', 'speed': 25, 'land_animal': True}
            }
        },
        
    "Imaginary": {
        "Winged" : {
            "Dragon" : {'name': 'Fire Dragon','speed': 100, 'land_animal': True},
            "Phoenix" : {'name': 'Phoenix', 'speed': 1500, 'land_animal': True}
            },
        "Legged" : {
            "Sphinx" : {'name': 'Sphinx','speed': 10, 'land_animal': True},
            "Minotaur" : {'name': 'Minotaur', 'speed': 5, 'land_animal': True}
            },
        "Other" :  {}
        }
   }

دسترسی به مقدارها در یک dict

می‌توانید با استفاده از یک کلید درون کروشه به یک value در دیکشنری دسترسی پیدا کنید. اگر کلیدی در دیکشنری وجود نداشته باشد، یک 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'

دسترسی به مدخل‌های دیکشنری تودرتو

برای دسترسی به مدخل‌های دیکشنری‌های تودرتو، از کروشه‌های پیاپی استفاده کنید. اگر کلید موردنظر وجود نداشته باشد، همان KeyError معمول پرتاب می‌شود:

# Using the animals nested dictionary.
>>> animals["Real"]["winged"]["Kestrel"]["speed"]
15

>>> animals["Imaginary"]["winged"]["Kestrel"]["speed"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Kestrel'

برای جلوگیری از KeyError می‌توان از .get() استفاده کرد، اما فراخوانی‌های .get() باید زنجیره‌ای باشند:

# Using the animals nested dictionary.
# Note the use of parenthesis to enable placing the 
# .get() calls on separate lines.
>>> (animals.get("Imaginary", {})
            .get("Legged", {})
            .get("Sphinx", {})
            .get("Color", "I have no idea!"))
'I have no idea!'

تغییر دادن یا افزودن مقدارهای دیکشنری

می‌توانید 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 و del)

می‌توانید از متد <dict>.pop(<key>) برای حذف یک مدخل دیکشنری استفاده کنید. <dict>.pop() جفت (key، value) را حذف می‌کند و value را برای استفاده بازمی‌گرداند. مانند <dict>.get()، متد <dict>.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'

همچنین می‌توانید از دستور del برای حذف یک یا چند مدخل استفاده کنید. اگر مدخلی که باید حذف شود در دیکشنری پیدا نشود، KeyError پرتاب می‌شود:

>>> wombat = {'name': 'Wombat',
              'speed': 23,
              'land_animal': True,
              'color': 'Brindle',
              'talent': 'Singing',
              'size': 'small'}

# Remove a single entry from the dictionary.
>>> del wombat["color"]
>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True, 'talent': 'Singing', 'size': 'small'}


# Remove multiple entries from the dictionary.
>>> del wombat["talent"], wombat["size"]
>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True}


# Attempting a deletion of a non-existent key raises a KeyError
>>> del wombat["number_of_legs"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'number_of_legs'

پیمایش یک دیکشنری با حلقه

پیمایش یک دیکشنری با for item in dict یا while item به‌طور پیش‌فرض روی کلیدها تکرار می‌کند. می‌توانید در همان حلقه با استفاده از کروشه به مقدارها دسترسی پیدا کنید:

>>> for key in bear:
...     print((key, bear[key])) # <--This prints a tuple of (key, value).
('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() کلیدها را برمی‌گرداند و .values() مقدارها را.

برای توضیح مفصل دیکشنری‌ها در پایتون، مستندات رسمی نقطه‌ی شروع عالی‌ای است، یا می‌توانید آموزش W3-Schools را هم ببینید.

گسترش قابلیت‌های دیکشنری: ماژول collections

ماژول collections قابلیت‌های تخصصی به انواع داده‌ی مبتنی بر مجموعه‌ی استاندارد پایتون (dict، set، list، tuple) اضافه می‌کند. سه مورد از مفیدترین کلاس‌های مبتنی بر دیکشنری عبارت‌اند از:

  • Counter به‌طور خودکار عناصر را می‌شمارد و آن‌ها را در یک dict برمی‌گرداند که عناصر به‌عنوان کلید و تعدادشان به‌عنوان مقدار هستند.
  • OrderedDict متدهایی دارد که برای تنظیم ترتیب مدخل‌های دیکشنری تخصصی شده‌اند.
  • defaultdict از یک متد کارخانه برای تعیین مقدار پیش‌فرض استفاده می‌کند، در صورتی که هنگام بازیابی یا مقداردهی به یک مدخل دیکشنری، key پیدا نشود.
ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

دیکشنری را یاد بگیرید

تمرین کردن قفل شده است

برای تمرین دیکشنری قفل 4 تمرین دیگر را باز کنید