phonebook = {"Ali": "0912‑123‑4567", "Sara": "0935‑987‑6543"}
print(phonebook["Sara"]) # 0935‑987‑6543
ساختار Dictionary
هر Dictionary مجموعهای از آیتمهاست که هر آیتم از یک کلید (key) و یک مقدار (value) تشکیل شده است. به زبان ساده، Dictionary ارتباط یا نگاشتی میان کلیدها و مقادیر ایجاد میکند؛ یعنی هر کلید به یک مقدار خاص اشاره میکند. برای تعریف یک دیکشنری در زبان پایتون، از علامت آکولاد {} استفاده میکنیم و داخل آن، هر جفت کلید:مقدار را با ویرگول از هم جدا میکنیم. برای مثال:
user_info = {"name": "Ali", "age": 25, "city": "Tehran"}
همچنین از نسخه 3.7 به بعد، دیکشنریهای پایتون ترتیب ورود اقلام را حفظ میکنند (یعنی Ordered هستند)؛ با این وجود، نباید آنها را با ساختارهای مرتبشده بر اساس مقدار یا کلید اشتباه گرفت. به طور خلاصه، ویژگیهای ساختاری مهم Dictionary عبارتاند از:
- نگهداری داده به صورت جفتهای کلید-مقدار (قابلیت کنار هم قرار دادن یک مقدار و یک شناسه یا کلید مشخص)
- کلیدهای یکتا و غیرقابل تغییر (هر کلید منحصربهفرد است و تایپ های mutable مثل list یا dict به عنوان کلید قابل استفاده نیستند)
- مقادیر قابل تغییر و متنوع (value میتواند هر نوع دادهای از جمله عدد، رشته، لیست، شیء و حتی دیکشنری دیگر باشد)
- قابل تغییر بودن ساختار (میتوان پس از ایجاد، آیتم جدید اضافه کرد یا آیتمها را تغییر داد یا حذف کرد)
- سرعت بالا در دسترسی به آیتمها (جستجوی سریع بر اساس کلید به دلیل استفاده از الگوریتم هش)
ایجاد Dictionary
برای ساخت یک Dictionary جدید در پایتون راههای مختلفی وجود دارد. سادهترین روش استفاده از آکولاد {} است. در این حالت، میتوانید هنگام تعریف، آیتمها را به شکل کلید:مقدار مشخص کنید. در ادامه چند روش رایج ایجاد دیکشنری را میبینیم: ایجاد به صورت مستقیم با مقداردهی: همانطور که در مثال قبل دیدیم، میتوان هنگام تعریف متغیر، محتویات Dictionary را داخل {} نوشت. به عنوان نمونه:
prices = {"apple": 1000, "banana": 500, "orange": 750}
print(prices) # {"apple": 1000, "banana": 500, "orange": 750
در این مثال، یک دیکشنری به نام prices ایجاد شده که قیمت چند میوه را نگهداری میکند. سه کلید “apple”, “banana”, “orange” به مقادیر عددی مربوط به قیمتها مرتبط شدهاند.
استفاده از تابع ()dict
روش دیگر، به کار بردن تابع ()dict برای ساخت دیکشنری است که یک تابع built in هست . این تابع میتواند یک دنباله (مثلاً لیستی از تاپلها) یا بصورت کلید و مقدار ورودی بپذیرد. برای مثال:
# ایجاد دیکشنری از طریق لیستی از تاپلها
items = [("pen", 2), ("notebook", 5)]
stock = dict(items)
print(stock) # {"pen": 2, "notebook": 5}
# ایجاد دیکشنری با استفاده از آرگومانهای کلیدی
person = dict(name="Sara", age=30, city="Shiraz")
print(person) # {"name": "Sara", "age": 30, "city": "Shiraz"}
- در مثال بالا، ابتدا لیستی از تاپلها تشکیل شده و سپس با dict(items) به دیکشنری تبدیل گردیده است. در نمونهی دوم، از آرگومانهای استفاده شده که در آن هر اسم آرگومان تبدیل به کلید (رشته) و مقدار آن تبدیل به value میشود.
ایجاد دیکشنری خالی و افزودن تدریجی آیتمها
شما میتوانید یک Dictionary خالی بسازید و سپس به مرور به آن عنصر اضافه کنید. برای ساخت دیکشنری خالی از {} یا ()dict بدون آرگومان استفاده میکنیم. سپس با دستور انتساب برای یک کلید، مقدار موردنظر را ذخیره میکنیم:
student = {} # دیکشنری خالی
student["name"] = "Reza" # افزودن یک آیتم جدید
student["score"] = 85 # افزودن آیتم دیگر
print(student) # {"name": "Reza", "score": 85}
- ابتدا student به صورت یک دیکشنری خالی تعریف شده و سپس دو آیتم با کلیدهای “name” و “score” به آن اضافه شدهاند. پس از انتساب، دیکشنری شامل دو جفت key:value است.
علاوه بر روشهای بالا، برای ایجاد سریع دیکشنریهای خاص میتوان از روشهایی مثل Dictionary comprehension نیز استفاده کرد که در بخش نکات پیشرفته به آن خواهیم پرداخت. فعلاً با همین روشهای پایه میتوانید هر دیکشنری دلخواهی را ایجاد کنید.
دسترسی به مقادیر و بهروزرسانی دیکشنری
پس از ساخت یک Dictionary، مهمترین عملیات، دسترسی به مقدار مرتبط با یک کلید و تغییر یا افزودن آیتمها است. دسترسی به یک مقدار از طریق قرار دادن کلید در علامتهای [] انجام میشود . به مثال زیر توجه کنید:
info = {"name": "Ali", "age": 25}
print(info["name"]) # Ali
در اینجا با info[“name”] به مقدار مرتبط با کلید “name” دسترسی پیدا کردهایم که مقدار “Ali” را برمیگرداند. اگر کلیدی که وجود ندارد را به این روش فراخوانی کنید، پایتون خطای KeyError را ایجاد میکند. برای جلوگیری از این خطا میتوانید ابتدا وجود کلید را با عملگر in بررسی کنید یا از متد ()get استفاده نمایید. متد get این امکان را میدهد که به جای خطا، یک مقدار پیشفرض برگردانده شود:
if "address" in info:
value = info["address"]
else:
value = None
print(value) # None
# روش دوم
value = info.get("address", None)
print(value) # None
در مثال بالا، چون کلید “address” در دیکشنری info وجود ندارد، روش اول با بررسی in مقدار None را در متغیر value قرار میدهد. روش دوم با یک خط و استفاده از info.get(“address”, None) همان نتیجه را بدون خطا حاصل میکند. (اگر مقدار پیشفرض را مشخص نکنیم، خود get در صورت نبود کلید مقدار None برمیگرداند.)
برای تغییر دادن مقدار یک کلید موجود نیز میتوان دوباره از عملگر انتساب =[“key”] استفاده کرد. کافیست به کلید موردنظر اشاره کرده و مقدار جدیدی به آن اختصاص دهید تا جایگزین مقدار قبلی شود. همچنین با همین روش میتوان آیتم جدیدی به dictionary افزود؛ اگر کلید وجود نداشت، یک جفت جدید ایجاد میشود . به این نمونه توجه کنید:
info["age"] = 26 # بهروزرسانی مقدار کلید "age"
info["address"] = "Iran" # افزودن کلید جدید "address"
print(info)
# {"name": "Ali", "age": 26, "address": "Iran"}
در ابتدا مقدار info[“age”] که 25 بود به 26 تغییر داده شده، سپس یک آیتم جدید با کلید “address” اضافه کردیم. حالا دیکشنری info دارای سه آیتم است. به این ترتیب عملیات اضافه یا ویرایش در Dictionary بسیار ساده انجام میشود.
حذف آیتمهای دیکشنری
گاهی نیاز است یک یا چند آیتم از Dictionary حذف شود. پایتون چندین روش برای حذف ارائه میدهد که میتوانید بسته به نیاز از آنها استفاده کنید:
استفاده از تابع pop(key)
این روش، آیتم مربوط به کلید مشخصشده را از دیکشنری حذف کرده و مقدار آن را برمیگرداند. اگر کلید وجود نداشته باشد و مقدار پیشفرضی ارائه نکرده باشید، خطا رخ میدهد. مثال:
scores = {"Ali": 85, "Sara": 90, "Reza": 75}
result = scores.pop("Sara")
print(result) # 90
print(scores) # {"Ali": 85, "Reza": 75}
- در اینجا آیتم با کلید “Sara” حذف شده و مقدار آن (90) در متغیر result ذخیره شده است. دیکشنری scores پس از pop فقط دو آیتم دارد. (میتوانید scores.pop(“Sara”, default_value) را به کار ببرید تا در صورت نبود کلید، به جای خطای KeyError مقدار default_value برگردد.)
استفاده از عبارت del
دستور del dict[key] آیتم مربوط به کلید دادهشده را از دیکشنری حذف میکند . برخلاف pop، این روش مقداری برنمیگرداند و صرفاً آیتم را حذف میکند:
person = {"name": "Zahra", "age": 20, "job": "developer"}
del person["job"]
print(person) # {"name": "Zahra", "age": 20}
- پس از اجرای del بالا، آیتمی که کلید “job” داشت حذف میشود.
استفاده از متد ()popitem
این متد بدون نیاز به مشخص کردن کلید، آخرین آیتم اضافهشده را از دیکشنری حذف کرده و به صورت یک تاپل (key, value) برمیگرداند. این رفتار در پایتون 3.7 به بعد به “آخرین آیتم” تغییر کرده است (در نسخههای قدیمیتر آیتمی تصادفی حذف میشد). مثال:
last_item = person.popitem()
print(last_item) # ('age', 20)
print(person) # {"name": "Zahra"}
در اینجا ()popitem آخرین عنصر (“age”: 20) را حذف و برگردانده است.
استفاده از متد ()clear
اگر بخواهید تمام آیتمها را یکجا پاک کنید، متد ()clear دیکشنری را خالی میکند:
scores.clear()
print(scores) # {}
هر یک از روشهای فوق کاربرد خاص خود را دارد. برای مثال، pop زمانی مفید است که به مقدار آیتم حذفشده نیاز داریم، del برای حذف ساده و سریع مناسب است، popitem برای ساختارهای پشته یا زمانی که ترتیب مهم است استفاده میشود، و clear برای ریستکردن کامل محتوا به کار میرود.
پیمایش Dictionary
پیمایش یا iteration روی دیکشنریها این امکان را میدهد که تمام آیتمهای آن را مرور کرده و به کلید و مقدار هر یک دسترسی پیدا کنید. چند روش متداول برای پیمایش یک Dictionary عبارتاند از:
حلقه for روی خود دیکشنری
سادهترین راه، استفاده مستقیم از دستور for روی شیء دیکشنری است. در این حالت، در هر تکرار حلقه یکی از کلیدهای دیکشنری به متغیر حلقه اختصاص داده میشود . به عنوان مثال:
user = {"name": "Ali", "age": 25, "city": "Tehran"}
for key in user:
print(key)
خروجی:
name
age
city
- همانطور که میبینید، به طور پیشفرض حلقه for فقط کلیدها را میدهد. ترتیب نمایش کلیدها معادل ترتیب درج آنها در دیکشنری است (در نسخههای جدید پایتون).
استفاده از متد ()keys یا ()values: متد ()keys لیستی از تمام کلیدهای دیکشنری و متد ()values لیستی از تمامی مقادیر را برمیگرداند . میتوانید با استفاده از این متدها نیز حلقهنویسی کنید یا آنها را به لیست تبدیل کنید. برای مثال:
for val in user.values():
print(val)
- خروجی بالا تمام مقادیر (“Ali”, 25, “Tehran”) را چاپ میکند. اگر نیاز به لیست معمولی از کلیدها یا مقادیر داشتید، میتوانید از list(user.keys()) استفاده کنید. اما در اغلب موارد نیازی به تبدیل به لیست نیست، زیرا روی همان view object هم میتوان پیمایش کرد.
استفاده از متد ()items
اگر بخواهید همزمان به key و value دسترسی داشته باشید، بهترین روش استفاده از ()dict.items است. این متد مجموعهای قابل پیمایش از تاپلهای (کلید, مقدار) را برمیگرداند:
for k, v in user.items():
print(f"{k} -> {v}")
خروجی:
name -> Ali
age -> 25
city -> Tehran
- در هر دور حلقه، k حاوی کلید و v حاوی مقدار مربوط به آن کلید است. این روش خواناترین و متداولترین راه برای پیمایش کامل یک دیکشنری است.
به کمک این روشها میتوانید به راحتی روی تمام آیتمهای یک Dictionary حرکت کنید. برای مثال، اگر بخواهیم مجموع مقادیر عددی در یک دیکشنری را حساب کنیم:
scores = {"Ali": 85, "Sara": 90, "Reza": 75}
total = 0
for score in scores.values():
total += score
print(total) # 250
در این قطعهکد، با پیمایش روی ()scores.values همه نمرات جمعآوری شده و حاصل در متغیر total بهدست آمده است.
نکته: در صورت نیاز به پیمایش مرتبشده (مثلاً بر اساس کلیدها)، میتوانید از تابع ()sorted روی کلیدها یا آیتمها استفاده کنید. برای نمونه :for k in sorted(user) کلیدها را به ترتیب حروف الفبا پیمایش خواهد کرد.
متد های دیکشنری در پایتون
| Function | Description | copy |
|---|---|---|
| all() | اگر تمام آیتمها truthy باشند True و در غیر این صورت False برمیگرداند. | |
| any() | اگر حداقل یک عنصر در iterable truthy باشد True و در غیر این صورت False برمیگرداند. | |
| len() | یک عدد صحیح که تعداد آیتمهای شیء ورودی را نشان میدهد، برمیگرداند. | |
| max() | بزرگترین مقدار را در یک iterable یا مجموعه آرگومانها برمیگرداند. | |
| min() | کوچکترین مقدار را در یک iterable یا مجموعه آرگومانها برمیگرداند. | |
| sorted() | یک لیست جدید مرتبشده از عناصر iterable برمیگرداند. | |
| sum() | جمع یک مقدار شروع و مقادیر iterable را از چپ به راست محاسبه و برمیگرداند. |
- truthy در پایتون به معنی هر شیء یا مقداری که «خالی» یا معادلِ صفر نباشد
نکات پیشرفته و ترفندها دیکشنری
در این بخش به چند تکنیک و نکته کاربردی درباره Dictionary اشاره میکنیم که میتواند برای کاربران حرفهایتر مفید باشد:
تولید دیکشنری با Dictionary Comprehension
squares = {x: x**2 for x in range(1, 6)}
print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
- در این مثال، x به عنوان کلید و x**2 به عنوان مقدار در دیکشنری squares درج شده است. این تکنیک در مواردی که نیاز به map کردن از یک مجموعه به مجموعهای دیگر داریم، بسیار کارآمد و مختصر است.
استفاده از متد get برای مقدار پیشفرض
متد get تنها برای جلوگیری از خطا کاربرد ندارد، بلکه میتوان از آن برای سادهسازی کد نیز بهره برد. یک الگوی رایج، استفاده از get در زمان شمارش تکرار عناصر است. فرض کنید لیستی از کلمات داریم و میخواهیم فراوانی هر کلمه را بشماریم:
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
freq = {}
for w in words:
freq[w] = freq.get(w, 0) + 1
print(freq) # {"apple": 3, "banana": 2, "orange": 1}
- در این قطعه کد، با هر بار مشاهدهی کلمه، مقدار فعلی آن کلید از دیکشنری freq گرفته شده و ۱ واحد به آن اضافه میشود. اگر کلید وجود نداشت، get مقدار پیشفرض 0 را برمیگرداند که بدین ترتیب آن کلمه اولین بار شمارش خواهد شد. نتیجهی نهایی فراوانی تکرار هر کلمه در دیکشنری freq است. این روش بهمراتب از بررسی شرطی وجود کلید و افزایش مقدار، خواناتر و کوتاهتر است.
ادغام و بهروزرسانی دیکشنریها
برای ترکیب دو دیکشنری یا بهروزرسانی مقادیر یکی بر اساس دیگری، میتوانید از متد ()update استفاده کنید. همچنین در پایتون 3.9 به بعد عملگر اتحاد | اضافه شده است که دو دیکشنری را با هم ترکیب میکند.
a = {"x": 1, "y": 2}
b = {"y": 3, "z": 4}
a.update(b)
print(a) # {"x": 1, "y": 3, "z": 4}
c = {"x": 1, "y": 2} | {"y": 3, "z": 4}
print(c) # {"x": 1, "y": 3, "z": 4}
- در نمونهی بالا، a.update(b) تمامی آیتمهای دیکشنری b را به a اضافه میکند؛ اگر کلیدی مشترک باشد (مثل “y”)، مقدار موجود در b جایگزین میشود. نتیجهی a پس از بهروزرسانی، ترکیب دو دیکشنری است. به شکل مشابه، استفاده از | نیز دیکشنری جدیدی c میسازد که حاوی ترکیب a و b است (بدون تغییر دادن آنها). این قابلیتها برای ادغام تنظیمات، بهروزرسانی پیکربندیها یا تجمیع نتایج چند ساختار داده مفید هستند.
متد کاربردی setdefault
این متد شبیه به get عمل میکند با این تفاوت که در صورت نبود کلید، علاوه بر بازگرداندن مقدار پیشفرض، همان مقدار را به دیکشنری هم اضافه میکند. کاربرد آن زمانی است که میخواهید مطمئن شوید یک کلید حتماً در دیکشنری وجود دارد سپس روی مقدار آن عملیاتی انجام دهید. برای مثال، فرض کنید میخواهیم لیستی از مقادیر را برای هر کلید جمعآوری کنیم:
data = {"A": 1, "B": 2, "C": 3, "D": 4}
groups = {}
for key, val in data.items():
group_key = "even" if val % 2 == 0 else "odd"
groups.setdefault(group_key, []).append(val)
print(groups) # {"odd": [1, 3], "even": [2, 4]}
- در اینجا از setdefault برای ایجاد کلیدهای “even” و “odd” در دیکشنری groups استفاده شده است. اگر کلید وجود نداشته باشد، یک لیست خالی به عنوان مقدار پیشفرض اضافه میشود و سپس append روی آن انجام میدهیم. این روش کد را نسبت به استفاده از شرط if کوتاهتر میکند.
حفظ ترتیب عناصر (OrderedDict)
همانطور که گفته شد، دیکشنریهای معمولی در پایتون ۳.۷ به بعد ترتیب ورود عناصر را نگه میدارند. در مواردی که از نسخههای قدیمیتر استفاده میشود یا نیاز به قابلیتهای بیشتر برای ترتیب داریم، کلاس OrderedDict در ماژول collections این امکان را میدهد که یک دیکشنری مرتب داشته باشیم. هرچند امروزه با وجود ویژگی ترتیب در dict پیشفرض، کمتر به آن نیاز پیدا میکنید، ولی دانستن آن خالی از لطف نیست.
خطاها و اشتباهات رایج در دیکشنریها
کار با دیکشنریها عموماً ساده است، اما برخی خطاها و اشتباهات رایج بین برنامهنویسان (بهویژه مبتدیان) مشاهده میشود که در ادامه به چند مورد مهم اشاره میکنیم:
خطای KeyError در دسترسی به کلید ناموجود
همانطور که پیشتر گفتیم، اگر سعی کنید با dict[key] به کلیدی که وجود ندارد دسترسی پیدا کنید، KeyError رخ میدهد. این خطا به معنای “یافت نشدن کلید” است. برای جلوگیری از آن، میتوانید ابتدا وجود کلید را با in چک کنید یا از get با مقدار پیشفرض استفاده کنید تا برنامه متوقف نشود. همچنین در موارد استفاده از ورودی کاربر برای کلید، بهتر است همیشه این موضوع را در نظر بگیرید.
استفاده از typeهای غیرمجاز به عنوان کلید
یک اشتباه متداول این است که نوعهای تغییرپذیر مثل list یا dict را به عنوان کلید استفاده کنیم. این کار مجاز نیست، زیرا این نوعها هشپذیر نیستند و پایتون نمیتواند برای آنها مکان ثابتی در ساختار هش دیکشنری اختصاص دهد. نتیجهی چنین عملیاتی خطایی مانند TypeError: unhashable type: ‘list’ خواهد بود. اگر نیاز دارید از یک مقدار قابل تغییر به عنوان کلید استفاده کنید، میتوانید نسخهی غیرقابل تغییر آن (مثلاً تبدیل لیست به تاپل) را به کار ببرید.
اشتباه در کپی کردن دیکشنری (aliasing)
فرض کنید یک دیکشنری دارید و میخواهید یک کپی مستقل از آن ایجاد کنید. اگر به سادگی بنویسید new_dict = original_dict، در واقع هر دو متغیر به یک شیء یکسان اشاره خواهند کرد و تغییر در یکی روی دیگری نیز اثر میگذارد. این یک دام رایج است. برای حل این موضوع، از متد ()copy یا تابع ()dict استفاده کنید:
original = {"a": 1, "b": 2}
new_dict = original.copy() # کپی سطح یک (shallow copy)
new_dict_independent = dict(original) # روش دیگر کپی
- اکنون تغییر در new_dict و new_dict_independent تاثیری روی original نخواهد داشت. (توجه داشته باشید که این کپی به صورت سطحی است؛ اگر مقادیر خودشان ساختارهای mutable مثل لیست یا دیکشنری یا Set باشند، برای کپی عمیق باید از copy.deepcopy استفاده کنید.)
import copy
a = {"x": [1, 2, 3]}
b = copy.copy(a) # کپی سطحی
c = copy.deepcopy(a) # کپی عمیق
تغییر در لیست [1,2,3] در متغییر a باعث تغییر لیست در متغیر b هم میشود اما با کپی عمیق (deepcopy) تمام اجزای داخلی یک شیء (مثل لیستها یا دیکشنریهای تو در تو) هم بهصورت مستقل کپی میشوند، بنابراین تغییر در لیست [1,2,3] کپیشده درc روی نسخهی اصلی اثری ندارد.
مزیت اصلی deep copy، استقلال کامل همه دادههاست، اما در مقابل، مصرف حافظه و زمان بیشتری نسبت به کپی سطحی دارد.
تغییر آیتمهای دیکشنری حین پیمایش
افزودن یا حذف آیتمهای یک دیکشنری در حین اینکه در حال پیمایش آن با for هستید میتواند منجر به رفتارهای غیرمنتظره یا خطای RuntimeError شود. برای جلوگیری از این مشکل، اگر نیاز به حذف آیتمها در خلال پیمایش دارید، میتوانید از روی یک کپی از کلیدها حلقه بروید:
for k in list(my_dict.keys()):
if condition(k):
del my_dict[k]
- با این روش، دیکشنری اصلی را حین پیمایش تغییر نمیدهید بلکه پس از گرفتن لیست کلیدها، روی آن لیست حرکت میکنید و آنگاه آیتمهای موردنظر را حذف میکنید.







