ساختار داده دیکشنری در پایتون
ساختار داده دیکشنری در پایتون
ساختار داده دیکشنری در پایتون
در پایتون، برای ذخیرهسازی و مدیریت دادههای ساختاریافته و رابطهای، از ساختار دادهای به نام دیکشنری (Dictionary) استفاده میشود. برخلاف دنبالههایی مثل لیست که بر پایه موقعیت عددی هستند، دیکشنریها دادهها را در قالب جفتهای «کلید: مقدار» (Key-Value Pairs) نگهداری میکنند.
دیکشنری چیست ؟
دیکشنری یک ساختار داده نگاشتی (Mapping)، مرتب (Insertion-Ordered از پایتون ۳.۷ به بعد)، تغییرپذیر (Mutable) و با کلیدهای یکتا (Unique) است.
- کلید (Key): به عنوان شناسه منحصربهفرد داده عمل میکند و باید تغییرناپذیر (Immutable) مانند رشته، عدد یا تاپل باشد.
- مقدار (Value): داده متناظر با کلید است و هر نوع دادهای میتواند باشد.
- کاربردها:
- ذخیره اطلاعات شناسنامهای و رکوردهای پایگاه داده (مانند پرونده کاربر یا بیمار).
- مدیریت تنظیمات (Configuration) و فایلهای پیکربندی سیستم.
- تبادل دادهها در وب و سرویسهای API در فرمت JSON.
- ساخت جدولهای جستوجو (Lookup Tables) و شمارندههای سریع
نحوه ساخت دیکشنری
دیکشنری با آکولاد {} یا با استفاده از تابع سازنده dict() ساخته میشود:
# دیکشنری خالی
empty_dict = {}
# دیکشنری ساده
user = {"name": "Sara", "age": 28}
دیکشنری میتواند انواع داده مختلف را در کلیدها و مقادیر خود جا دهد (حتی لیست و دیکشنری دیگر به عنوان مقدار):
patient_record = {
"patient_id": 1042, # عدد صحیح
"name": "Mina", # رشته
"is_admitted": True, # بولین
"heart_rate_avg": 72.4, # اعشاری
"leads": ["Lead I", "Lead II"], # لیست
"metadata": {"sampling_rate": 500} # دیکشنری تودرتو
}
نحوه دسترسی و اندیسگذاری و مفهوم اسلایسینگ
- اندیسگذاری (Indexing): دیکشنریها اندیس عددی ترتیبی مثل
[0]ندارند؛ دسترسی به مقادیر مستقیماً از طریق کلیدها انجام میشود:
info = {"brand": "Tesla", "model": "Model 3"}
print(info["brand"]) # خروجی: 'Tesla'
- عدم وجود اسلایسینگ (Slicing): دیکشنریها از برشدادن یا اسلایسینگ (مانند
dict[0:2]) پشتیبانی نمیکنند؛ زیرا مبتنی بر برچسب یا کلید هستند و مفهومی به نام توالی اندیسی ندارند.
متدهای پرکاربرد دیکشنری

متد get(key, default)
- توضیح: مقدار متناظر با کلید را برمیگرداند. اگر کلید وجود نداشته باشد، به جای ایجاد خطای
KeyError، مقدار پیشفرض را میدهد. - صورت مسئله: میخواهیم وضعیت بیمه یک بیمار را دریافت کنیم؛ در صورتی که ثبت نشده باشد، مقدار
"نامشخص"برگردانده شود.
patient = {"name": "Ali", "age": 45}
status = patient.get("insurance", "نامشخص")
print(status) # خروجی: نامشخص
متد keys()
- توضیح: نمایی (View) از تمامی کلیدهای موجود در دیکشنری را بازمیگرداند.
- صورت مسئله: میخواهیم لیست سنسورهایی که در حال حاضر داده ثبت کردهاند را استخراج کنیم.
readings = {"temp": 24.5, "pressure": 101.3, "humidity": 60}
sensor_list = readings.keys()
print(sensor_list) # خروجی: dict_keys(['temp', 'pressure', 'humidity'])
متد values()
- توضیح: نمایی از تمام مقادیر ذخیرهشده در دیکشنری را استخراج میکند.
- صورت مسئله: میخواهیم تمام نمرات ذخیرهشده دانشجو را بدون کلید نام درسها به دست آوریم.
grades = {"Math": 18.5, "Physics": 17.0, "Programming": 20.0}
all_scores = grades.values()
print(all_scores) # خروجی: dict_values([18.5, 17.0, 20.0])
متد items()
- توضیح: جفتهای «کلید، مقدار» را به صورت تاپلهای دونفره بازمیگرداند؛ مناسب برای پیمایش با حلقه.
- صورت مسئله: میخواهیم شناسه خطا و پیام مربوط به آن را خط به خط چاپ کنیم.
errors = {404: "Not Found", 500: "Server Error"}
for code, msg in errors.items():
print(f"Error {code}: {msg}")
# خروجی:
# Error 404: Not Found
# Error 500: Server Error
متد update(other_dict)
- توضیح: دیکشنری را با جفتهای جدید ادغام کرده یا مقادیر کلیدهای تکراری را بهروزرسانی میکند.
- صورت مسئله: میخواهیم مشخصات جدید شماره تماس را به پرونده کاربر اضافه کنیم.
user_profile = {"id": 101, "name": "Reza"}
user_profile.update({"phone": "09120000000", "name": "Reza Rahimi"})
print(user_profile) # خروجی: {'id': 101, 'name': 'Reza Rahimi', 'phone': '09120000000'}
متد pop(key, default)
- توضیح: جفت کلید و مقدار مشخصشده را از دیکشنری حذف کرده و مقدار آن را برمیگرداند.
- صورت مسئله: میخواهیم توکن موقت احراز هویت را پس از دریافت از دیکشنری خارج و حذف کنیم.
session = {"user": "admin", "token": "xyz123"}
token = session.pop("token")
print("توکن حذف شده:", token) # خروجی: xyz123
print("دیکشنری باقیمانده:", session) # خروجی: {'user': 'admin'}
متد popitem()
- توضیح: آخرین جفت (کلید، مقدار) اضافهشده به دیکشنری را حذف کرده و به شکل یک تاپل برمیگرداند.
- صورت مسئله: میخواهیم آخرین ورودی پردازشنشده را از لاگ موقت خارج کنیم.
logs = {"log1": "OK", "log2": "WARN", "log3": "FAIL"}
last_entry = logs.popitem()
print("حذف شد:", last_entry) # خروجی: ('log3', 'FAIL')
print("لاگها:", logs) # خروجی: {'log1': 'OK', 'log2': 'WARN'}
متد setdefault(key, default)
- توضیح: اگر کلید وجود داشته باشد مقدارش را برمیگرداند؛ اگر نباشد، کلید را با مقدار پیشفرض ثبت کرده و بازمیگرداند.
- صورت مسئله: میخواهیم اگر نقشی برای کاربر تعریف نشده بود، نقش پیشفرض
"viewer"برای او ذخیره شود.
user_role = {"username": "mina_n"}
role = user_role.setdefault("role", "viewer")
print("نقش:", role) # خروجی: viewer
print(user_role) # خروجی: {'username': 'mina_n', 'role': 'viewer'}
متد copy()
- توضیح: یک کپی سطحی و مستقل از دیکشنری میسازد تا تغییرات نسخه جدید روی دیکشنری اصلی اثر نگذارد.
- صورت مسئله: میخواهیم پیش از تغییر تنظیمات اولیه، یک نسخه پشتیبان از دیکشنری تنظیمات داشته باشیم.
config = {"theme": "dark", "volume": 80}
config_backup = config.copy()
config["volume"] = 90
print("اصلی:", config) # خروجی: {'theme': 'dark', 'volume': 90}
print("پشتیبان:", config_backup) # خروجی: {'theme': 'dark', 'volume': 80}
متد clear()
- توضیح: تمامی اعضا و جفتهای کلید-مقدار دیکشنری را کاملاً پاک میکند.
- صورت مسئله: میخواهیم کش موقت سیستم را خالی کنیم.
cache = {"page1": "cached_data", "page2": "cached_data"}
cache.clear()
print(cache) # خروجی: {}
متد fromkeys(keys, value)
- توضیح: یک دیکشنری جدید بر پایه یک دنباله از کلیدها و با یک مقدار پیشفرض مشترک میسازد.
- صورت مسئله: میخواهیم وضعیت اولیه تمام پورتهای شبکه را روی وضعیت
"closed"قرار دهیم.
ports = [80, 443, 8080]
port_status = dict.fromkeys(ports, "closed")
print(port_status) # خروجی: {80: 'closed', 443: 'closed', 8080: 'closed'}
۵. محدودیت دیکشنریها:
دیکشنریها به هیچ وجه امکان انجام عملیات ریاضی و برداری مستقیم را ندارند:
- نمیتوان دو دیکشنری عددی را با عملگر
+یا*با یکدیگر جمع یا ضرب کرد. - اعمال ریاضی روی دیکشنری باعث ایجاد خطای
TypeErrorمیشود.
dict_a = {"x": 10, "y": 20}
dict_b = {"x": 5, "y": 15}
# دستور زیر با خطای TypeError مواجه میشود:
# result = dict_a + dict_b
نکته: برای انجام محاسبات ریاضی و جدولی روی دادههای ساختاریافته، در پایتون از فریمورکها و کتابخانههای تخصصی مانند Pandas (DataFrame) استفاده میشود.
کلیدها باید «غیرقابل تغییر» باشند
کلید دیکشنری فقط میتواند از انواع دادههای غیرقابل تغییر (Immutable) باشد، نه لیست و دیکشنری (ساختارهای قابل ویرایش). دلیل آن به «تابع هش» (Hash Function) برمیگردد: دیکشنری کلیدها را به این تابع میسپارد تا به یک «مقدار هش» ثابت تبدیل شوند و جستجو بر پایه همین مقدار انجام شود. برای همین کلید قابل ویرایش، غیرقابل هش (unhashable) است و خطای unhashable type رخ میدهد.
دادههای مجاز برای کلید: رشتهها، اعداد صحیح، اعداد اعشاری، مقادیر True/False و تاپل.
#کلیدهای مجاز
d1 = {
"name": "Ali", # رشته
1: "one", # عدد صحیح
2.5: "two", # عدد اعشاری
True: "yes", # بولین
(1, 2): "tuple" # تاپل
}
print(d1[(1, 2)]) # خروجی: tuple
# ❌ خطا: لیست قابل تغییر است و نمیتواند کلید باشد
# d2 = {["a", "b"]: "value"} # TypeError: unhashable type: 'list'
کلیدها باید منحصربهفرد باشند
دیکشنری هر کلید منحصربهفرد را به یک مقدار نگاشت میکند. مقادیر میتوانند تکراری یا از هر نوعی باشند، اما کلید تکراری مجاز نیست. اگر هنگام افزودن آیتم جدید از کلید تکراری استفاده کنید، مقدار جدید جایگزین مقدار قبلی میشود.
{"Ali": 18, "Sara": 19, "Ali": 20} # کلید تکراری
print(score) # خروجی: {'Ali': 20, 'Sara': 19} → مقدار جدید جایگزین شد
# افزودن با کلید تکراری: مقدار قبلی بازنویسی میشود
score["Sara"] = 17
print(score) # خروجی: {'Ali': 20, 'Sara': 17}
۶. سه مثال کاربردی
مثال ۱: شمارش بسامد و فرکانس تکرار دادهها
استفاده از دیکشنری برای شمارش تعداد دستهبندیها (Frequency Counter) در یک لیست نمونه:
classes = ["NORM", "MI", "STTC", "NORM", "MI", "NORM"]
counts = {}
for label in classes:
if label in counts:
counts[label] += 1
else:
counts[label] = 1
print("تعداد هر کلاس:", counts)
# خروجی: {'NORM': 3, 'MI': 2, 'STTC': 1}
مثال ۲: سیستم مدیریت موجودی انبار فروشگاه
بررسی، افزایش یا کاهش موجودی کالاها با دسترسی کلید-محور:
inventory = {"apple": 50, "banana": 20, "orange": 35}
# فروش ۱۰ عدد سیب
inventory["apple"] -= 10
# افزودن کالای جدید
inventory["grape"] = 40
print("موجودی بهروز انبار:", inventory)
# خروجی: {'apple': 40, 'banana': 20, 'orange': 35, 'grape': 40}
مثال ۳: ساخت دفترچه تلفن و جستوجوی مستقیم
ذخیره اطلاعات تماس و جستوجوی سریع شماره با استفاده از نام فرد:
phonebook = {
"Ali": "09121111111",
"Sara": "09122222222",
"Mina": "09123333333"
}
contact_name = "Sara"
if contact_name in phonebook:
print(f"شماره {contact_name}: {phonebook[contact_name]}")
else:
print("مخاطب یافت نشد.")
# خروجی: شماره Sara: 09122222222
