سرنخ — خودآموز برنامه‌نویسی برای هوش مصنوعی (مقدماتی)

فصل ۴ از ۱۱

پیشرفت ترم
۰٪

ترم ۱ · پایتون از صفر، داخلِ Colab

دیکشنری: داده‌ای که اسم دارد

فصل ۴پیش‌نمایش رایگان
۹ دقیقه مطالعه فصل ۴

در این فصل چه یاد می‌گیری#

فهرست وقتی خوب است که ترتیب مهم باشد. ولی در دادهٔ واقعی معمولاً ترتیب را نمی‌دانی، اسم را می‌دانی: «قیمتِ این محصول»، «شهرِ این مشتری»، «دقتِ این مدل». در این فصل dict را می‌بینی — ظرفی که هر مقدار را زیرِ یک کلید نگه می‌دارد. این مهم‌ترین ساختارِ دادهٔ کلِ دوره است: پاسخِ هر API، هر ردیفِ یک جدول، و هر تنظیماتِ یک مدل دقیقاً همین شکل را دارد.

دو کشوی کنار هم: یکی با خانه‌های شماره‌دارِ یکسان و دیگری با پرونده‌هایی که هرکدام زبانهٔ برچسب‌دارِ متفاوت دارند

آخر این فصل می‌توانی:

  • یک dict بسازی و با کلید به مقدارهایش برسی
  • بگویی چه وقت dict بهتر از list است و برعکس
  • با get() بدونِ خطر خطا مقدار بگیری و با in وجودِ کلید را بپرسی
  • یک dict را تغییر بدهی: کلید اضافه، عوض، و حذف کنی
  • تفاوتِ tuple و set را با list در یک جمله بگویی

قبل از شروع#

از فصل ۳: list مقدارها را به‌ترتیب نگه می‌دارد و با اندیسِ عددی به آن‌ها می‌رسی.

از فصل ۳: متد چیست (x.append(...)) و «تغییرپذیری» یعنی چه.

📓 نوت‌بوک: نوت‌بوک این فصل را در Colab باز کن — همهٔ کدهای این فصل آماده و به‌ترتیب داخلش هست.

۱. ساختنِ یک دیکشنری#

product = {
    "name": "هدفون بلوتوثی",
    "price": 890000,
    "in_stock": True,
    "rating": 4.3,
}
print(product)
print(type(product))
{'name': 'هدفون بلوتوثی', 'price': 890000, 'in_stock': True, 'rating': 4.3}
<class 'dict'>

آکولاد یک dict می‌سازد. هر عنصرش یک جفت است: کلید (key) قبل از دونقطه، مقدار (value) بعدش. کلیدها اینجا متن‌اند، که رایج‌ترین حالت است.

دقت کن مقدارها لازم نیست هم‌نوع باشند: در همین یکی هم str هست، هم int، هم bool، هم float. این دقیقاً همان چیزی است که یک «ردیفِ داده» را توصیف می‌کند.

چرا اسم‌ها انگلیسی‌اند ولی مقدارها فارسی؟ چون کلید بخشی از کد است و مقدار بخشی از داده. کد را همیشه انگلیسی می‌نویسیم؛ داده هر زبانی که هست همان می‌ماند.

۲. رسیدن به یک مقدار#

print(product["name"])
print(product["price"])
print(f"{product['name']} — {product['price']} تومان")
هدفون بلوتوثی
890000
هدفون بلوتوثی — 890000 تومان

همان کروشه‌های list است، ولی به‌جای عدد، کلید داخلش می‌گذاری. این تفاوتِ اصلی است: در list باید بدانی چندمین است؛ در dict فقط باید اسمش را بدانی.

⚠️ مواظب باش: داخلِ f-string اگر از گیومهٔ دوتایی استفاده کرده‌ای، کلید را با گیومهٔ تکی بنویس ({product['name']}). دو گیومهٔ هم‌شکلِ تودرتو، f-string را می‌شکند.

۳. یک خطای واقعی: KeyError#

print(product["color"])
KeyError: 'color'

پیام کوتاه است و دقیقاً همان کلیدی را می‌گوید که پیدا نکرده. KeyError در کارِ داده بسیار رایج است، چون داده‌های واقعی همیشه همهٔ فیلدها را ندارند: بعضی محصول‌ها رنگ دارند و بعضی ندارند.

راهِ امن، متدِ get() است:

print(product.get("color"))
print(product.get("color", "نامشخص"))
print(product.get("price", 0))
None
نامشخص
890000

get() اگر کلید نباشد خطا نمی‌دهد؛ None برمی‌گرداند. و اگر آرگومانِ دومی بدهی، آن را به‌عنوانِ مقدارِ پیش‌فرض برمی‌گرداند.

None یک مقدارِ خاصِ پایتون است، یعنی «هیچ‌چیز». نه صفر است، نه رشتهٔ خالی — یعنی «اینجا مقداری وجود ندارد». در ترمِ ۲ با آن خیلی سروکار داری، چون خانه‌های خالیِ یک جدول دقیقاً همین‌اند.

راهِ دیگر، پرسیدنِ وجودِ کلید است:

print("price" in product)
print("color" in product)
True
False

چک کن: in روی dict کلیدها را می‌گردد، نه مقدارها. یعنی "هدفون بلوتوثی" in product جوابش False است، هرچند آن متن در دیکشنری هست — چون مقدار است نه کلید.

قبل از ادامه، جواب بده: کِی product["x"] را به‌کار ببری و کِی product.get("x") را؟ جواب: وقتی مطمئنی کلید باید وجود داشته باشد، کروشه بهتر است — چون اگر نبود، همان‌جا داد می‌زند و تو زودتر می‌فهمی داده‌ات خراب است. get() برای وقتی است که نبودنِ کلید یک حالتِ عادی و پیش‌بینی‌شده باشد. سکوتِ بی‌جا به‌اندازهٔ خطای بی‌جا بد است.

۴. تغییردادنِ دیکشنری#

product["color"] = "مشکی"
product["price"] = 850000
del product["rating"]
print(product)
print(len(product))
{'name': 'هدفون بلوتوثی', 'price': 850000, 'in_stock': True, 'color': 'مشکی'}
4

یک نکتهٔ ظریف: همان دستور هم اضافه می‌کند و هم عوض. product["color"] = ... وقتی color نبود آن را می‌سازد، و وقتی بود مقدارش را جایگزین می‌کند. پایتون هشدار نمی‌دهد.

این هم قدرت است و هم تله. اگر کلید را اشتباه تایپ کنی، به‌جای خطا یک کلیدِ تازه ساخته می‌شود و برنامه بی‌سروصدا کارِ غلط می‌کند:

product["prcie"] = 999
print(product.keys())
dict_keys(['name', 'price', 'in_stock', 'color', 'prcie'])

حالا دو کلیدِ قیمت داری و هیچ خطایی هم نگرفتی. keys() فهرستِ کلیدها را می‌دهد و اولین جایی است که وقتی چیزی درست کار نمی‌کند باید نگاهش کنی.

del product["prcie"]
print(product.keys())
dict_keys(['name', 'price', 'in_stock', 'color'])

📏 اندازه بگیر: هر وقت مقداری که انتظار داشتی در دیکشنری نبود، اول print(x.keys()) را بزن. غلطِ املاییِ کلید — که هیچ خطایی تولید نمی‌کند — یکی از بی‌سروصداترین باگ‌های کارِ داده است.

۵. tuple و set — دو خویشاوندِ کوتاه#

پایتون دو ظرفِ دیگر هم دارد که در این دوره کم‌تر ولی به‌جا استفاده می‌شوند.

point = (35.7, 51.4)
print(point[0])
print(type(point))

tags = {"صوتی", "بلوتوثی", "صوتی", "پرفروش"}
print(len(tags))
print(sorted(tags))
35.7
<class 'tuple'>
3
['بلوتوثی', 'صوتی', 'پرفروش']
  • tuple با پرانتز ساخته می‌شود و مثلِ list است با یک تفاوت: تغییرناپذیر است. بعد از ساختن نمی‌شود عنصرهایش را عوض کرد. برای چیزهایی که ذاتاً نباید عوض شوند (یک مختصات، یک جفتِ عرض و ارتفاع) دقیقاً همین را می‌خواهی. در ترمِ ۲ مرتب می‌بینی‌اش: شکلِ یک جدول همیشه یک tuple است.
  • set با آکولاد ساخته می‌شود ولی بدونِ کلید، و دو خاصیت دارد: تکراری نمی‌پذیرد و ترتیب ندارد. سه برچسب نوشتیم و «صوتی» دو بار آمد، ولی len می‌گوید سه — تکراری خودش حذف شد.

اینجا عمداً sorted(tags) را چاپ کردیم نه خودِ tags را، و دلیلش مهم است: set هیچ ترتیبی ندارد، پس اگر مستقیم چاپش کنی ممکن است هر بار به ترتیبِ متفاوتی ببینی‌اش. (sorted() هم مثلِ len() و max() یک تابعِ مستقل است: هر مجموعه‌ای را می‌گیرد و یک listِ تازهٔ مرتب‌شده برمی‌گرداند، بدونِ اینکه به اصل دست بزند.) هر وقت خروجی‌ای می‌سازی که قرار است کسِ دیگری هم ببیندش، مرتبش کن. این اولین نمونهٔ کوچکِ چیزی است که در کلِ دوره تعقیبش می‌کنیم: خروجی باید تکرارپذیر باشد.

💡 نکته: ساده‌ترین راهِ حذفِ تکراری‌ها از یک فهرست همین است: list(set(my_list)). فقط بدان که ترتیب را از دست می‌دهی.

۶. کِی list و کِی dict#

قاعدهٔ عملی ساده است:

  • اگر می‌پرسی «چندمی؟»list. مثلاً دمای هفت روزِ هفته، یا قیمتِ صد محصول به‌ترتیب.
  • اگر می‌پرسی «کدام؟»dict. مثلاً همهٔ اطلاعاتِ یک محصول، یا نمرهٔ هر شهر.

و در عمل، دادهٔ واقعی معمولاً ترکیبِ هر دو است: یک فهرست از دیکشنری‌ها. این دقیقاً شکلی است که پاسخِ یک API می‌آید و شکلی است که یک جدول را در پایتون نمایش می‌دهند:

products = [
    {"name": "هدفون", "price": 850000},
    {"name": "کیبورد", "price": 1200000},
    {"name": "ماوس", "price": 430000},
]
print(products[1]["name"])
print(len(products))
کیبورد
3

products[1] دیکشنریِ دوم را می‌دهد، و ["name"] از داخلِ همان دیکشنری نام را برمی‌دارد. این ساختار را خوب نگاه کن — در ترمِ ۲ که pandas را ببینی، خواهی دید یک جدولِ کامل دقیقاً همین است.

🤖 از دستیارت بپرس: «یک dict در پایتون را با یک list مقایسه کن: هرکدام برای چه نوع داده‌ای مناسب‌ترند؟ سه مثالِ واقعی بزن.» جوابش را با قاعدهٔ «چندمی؟ / کدام؟» در این بخش بسنج. اگر مثالی زد که با این قاعده جور درنمی‌آید، خودت در نوت‌بوک امتحانش کن.

واژه‌های تازهٔ این فصل#

کلمه تلفظ به حروف فارسی یعنی چه
dict دیکت ظرفی که هر مقدار را زیرِ یک کلید نگه می‌دارد
key / value کی / ولیو کلید و مقدار؛ دو نیمهٔ هر عنصرِ دیکشنری
None نان مقدارِ «هیچ‌چیز»؛ نه صفر، نه رشتهٔ خالی
KeyError کی اِرور کلیدی خواسته‌ای که در دیکشنری نیست
tuple تاپِل مثلِ list ولی تغییرناپذیر
set سِت مجموعهٔ بدونِ تکرار و بدونِ ترتیب

تمرین‌ها

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

در فصل بعد#

حالا می‌توانی داده را نگه داری، ولی کدت هنوز همیشه یک مسیرِ ثابت را می‌رود. فصلِ بعد اولین ابزارِ تصمیم‌گیری را می‌آورد: if. یاد می‌گیری کد را وادار کنی به مقدارها نگاه کند و بر اساسِ آن‌ها کارِ متفاوتی بکند — و همان‌جا می‌فهمی چرا تورفتگیِ خط در پایتون یک سلیقهٔ ظاهری نیست، بلکه بخشی از خودِ زبان است.

به آخر این فصل رسیدی!

اگر ساختی و جواب داد، این دکمه مال توست.