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

فصل ۶ از ۱۱

پیشرفت ترم
۰٪

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

حلقه: کد تکرار می‌کند

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

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

در فصلِ ۴ یک تمرین داشتی که گفتیم برای چهار محصول قابلِ‌تحمل است و برای چهارصد تا نه. این فصل همان بدهی را می‌پردازد. حلقه یعنی نوشتنِ کد یک بار و اجرای آن روی هر عنصرِ یک فهرست — چه ده تا باشد چه ده میلیون. این تنها فصلی است که بعدش کدت واقعاً شبیهِ کارِ داده می‌شود، و الگویی که اینجا یاد می‌گیری (بگرد، بشمار، جمع کن، فیلتر کن) دقیقاً همان کاری است که در ترمِ ۲ pandas برایت خودکار انجام می‌دهد.

یک نوار نقاله که قطعه‌ها را یکی‌یکی از زیر یک ایستگاه بازرسی عبور می‌دهد و شمارنده‌ای در کنارش

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

  • با for روی یک فهرست، یک دیکشنری و یک بازهٔ عددی راه بروی
  • با الگوی انباشتگر بشماری، جمع بزنی و فیلتر کنی
  • تفاوتِ for و while را بگویی و بدانی هرکدام کِی به‌کار می‌آید
  • با break و continue مسیرِ حلقه را عوض کنی
  • یک list comprehension ساده بنویسی و بگویی چرا خواناتر است

قبل از شروع#

از فصل ۳: list و len() و append().

از فصل ۴: dict و اینکه یک فهرست از دیکشنری‌ها شکلِ رایجِ دادهٔ واقعی است.

از فصل ۵: if و تورفتگی به‌عنوانِ ساختارِ زبان.

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

۱. اولین حلقه#

cities = ["تهران", "شیراز", "تبریز", "مشهد"]

for city in cities:
    print(city)
تهران
شیراز
تبریز
مشهد

این را بلند بخوان: «برای هر city در cities، چاپش کن». همان‌قدر ساده است که به‌نظر می‌رسد.

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

for city in cities:
    print(f"شهر: {city}")
    print(f"تعداد حروف: {len(city)}")

print("حلقه تمام شد")
شهر: تهران
تعداد حروف: 5
شهر: شیراز
تعداد حروف: 5
شهر: تبریز
تعداد حروف: 5
شهر: مشهد
تعداد حروف: 4
حلقه تمام شد

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

۲. range: وقتی فهرست نداری، شمارنده می‌خواهی#

for i in range(5):
    print(i)
0
1
2
3
4

range(5) پنج عدد می‌دهد: از صفر تا قبل از پنج. همان قاعدهٔ برشِ فصلِ ۳ است و همان دلیل را دارد: range(5) دقیقاً به‌اندازهٔ اندیس‌های یک فهرستِ پنج‌تایی عدد می‌دهد.

range دو و سه‌آرگومانی هم دارد:

for i in range(2, 6):
    print(i, end=" ")
print()

for i in range(0, 10, 3):
    print(i, end=" ")
print()
2 3 4 5 
0 3 6 9 

دو نکتهٔ کوچک در همین کد هست. آن end=" " به print می‌گوید به‌جای رفتن به خطِ بعد، یک فاصله بگذارد — فقط برای اینکه خروجی جمع‌وجور شود. و print() بدونِ هیچ‌چیزِ داخلِ پرانتز، یک خطِ خالی چاپ می‌کند؛ اینجا کارش این است که بعد از هر حلقه سرِ خطِ تازه برویم، وگرنه خروجیِ دو حلقه به هم می‌چسبید.

💡 نکته: اگر همزمان هم عنصر و هم شماره‌اش را می‌خواهی، به‌جای range(len(x)) از enumerate استفاده کن؛ خواناتر است و خطای اندیس نمی‌سازد.

for i, city in enumerate(cities):
    print(f"{i}: {city}")
0: تهران
1: شیراز
2: تبریز
3: مشهد

۳. الگوی انباشتگر: بشمار، جمع بزن، فیلتر کن#

این مهم‌ترین بخشِ فصل است. الگو همیشه یکی است: یک ظرفِ خالی بساز، در حلقه پُرش کن، بعد از حلقه استفاده‌اش کن.

products = [
    {"name": "هدفون", "price": 850000, "stock": 12},
    {"name": "کیبورد", "price": 1200000, "stock": 0},
    {"name": "ماوس", "price": 430000, "stock": 7},
    {"name": "وبکم", "price": 2100000, "stock": 3},
]

total = 0
for product in products:
    total = total + product["price"]

print(f"مجموع قیمت‌ها: {total}")
print(f"میانگین قیمت: {total / len(products)}")
مجموع قیمت‌ها: 4580000
میانگین قیمت: 1145000.0

متغیرِ total قبل از حلقه با صفر ساخته شد — این حیاتی است. اگر داخلِ حلقه می‌ساختی‌اش، هر دور از نو صفر می‌شد و آخرش فقط قیمتِ آخرین محصول را داشتی.

حالا فیلترکردن، که همان الگو با یک if است:

available = []
for product in products:
    if product["stock"] > 0:
        available.append(product["name"])

print(available)
print(f"{len(available)} محصول از {len(products)} تا موجود است")
['هدفون', 'ماوس', 'وبکم']
3 محصول از 4 تا موجود است

و پیدا کردنِ بیشینه، که همان الگو با یک مقایسه است:

most_expensive = products[0]
for product in products:
    if product["price"] > most_expensive["price"]:
        most_expensive = product

print(f"گران‌ترین: {most_expensive['name']} — {most_expensive['price']}")
گران‌ترین: وبکم — 2100000

چک کن: هر سه خروجی را با چشمِ خودت روی فهرستِ products بررسی کن. این عادت را از همین‌جا بگیر: هر عددی که کد تولید می‌کند، روی یک نمونهٔ کوچک با دست هم قابلِ بررسی است. در ترمِ ۳ که مدل بسازی، همین عادت تنها چیزی است که جلوی باورکردنِ یک عددِ غلط را می‌گیرد.

📏 اندازه بگیر: most_expensive را عمداً با products[0] شروع کردیم، نه با صفر یا با یک dict خالی. اگر با صفر شروع می‌کردی، مقایسهٔ dict با عدد خطا می‌داد؛ اگر فهرست خالی بود، همان خطِ اول IndexError می‌گرفت. مقدارِ اولیهٔ یک انباشتگر یک تصمیم است، نه یک جزئیات — و در فصلِ ۳ ترمِ ۳، همین ایده به «خطِ پایه» تبدیل می‌شود.

۴. break و continue#

for product in products:
    if product["stock"] == 0:
        continue
    if product["price"] > 2000000:
        print(f"خیلی گران است، جست‌وجو را متوقف می‌کنم: {product['name']}")
        break
    print(f"بررسی شد: {product['name']}")
بررسی شد: هدفون
بررسی شد: ماوس
خیلی گران است، جست‌وجو را متوقف می‌کنم: وبکم
  • continue یعنی «بقیهٔ این دور را رها کن و برو دورِ بعد». برای همین «کیبورد» که موجودی صفر داشت اصلاً چاپ نشد.
  • break یعنی «کلاً از حلقه بیرون بیا». برای همین بعد از «وبکم» حلقه تمام شد.

۵. while: وقتی نمی‌دانی چند بار#

for وقتی خوب است که بدانی روی چه چیزی راه می‌روی. گاهی نمی‌دانی — فقط یک شرطِ توقف داری:

balance = 1000000
months = 0

while balance > 0:
    balance = balance - 250000
    months = months + 1

print(f"بعد از {months} ماه موجودی تمام شد")
بعد از 4 ماه موجودی تمام شد

while تا وقتی شرطش True است تکرار می‌کند. و همین‌جا خطرش هم هست:

⚠️ مواظب باش: اگر شرطِ while هیچ‌وقت False نشود، حلقه تمام نمی‌شود. در Colab این یعنی سلولی که تا ابد می‌چرخد و باید با دکمهٔ ⏹ متوقفش کنی. قبل از اجرای هر while، این سؤال را از خودت بپرس: «کدام خط باعث می‌شود شرط بالاخره نادرست شود؟» اگر جوابی نداشتی، حلقه‌ات بی‌پایان است. در این دوره تقریباً همیشه for انتخابِ درست‌تر است.

۶. list comprehension: همان حلقه، یک خطی#

الگوی «فهرستِ خالی بساز، حلقه بزن، append کن» آن‌قدر رایج است که پایتون برایش یک شکلِ کوتاه دارد:

names = [product["name"] for product in products]
print(names)

cheap = [p["name"] for p in products if p["price"] < 1000000]
print(cheap)
['هدفون', 'کیبورد', 'ماوس', 'وبکم']
['هدفون', 'ماوس']

از راست به چپِ منطقی بخوانش: «برای هر product در products» ← «(اگر شرط برقرار بود)» ← «این را در فهرست بگذار».

این دقیقاً همان کارِ سه‌خطیِ بخشِ ۳ است، در یک خط. برای کارِ ساده خواناتر است؛ برای کارِ پیچیده خواناتر نیست و باید همان حلقهٔ معمولی را بنویسی. قاعدهٔ عملی: اگر در یک نگاه خوانده نشد، بشکنش.

🤖 از دستیارت بپرس: «این حلقهٔ پایتون را به یک list comprehension تبدیل کن و بعد خط به خط توضیح بده کدام تکه کجا رفت» — و حلقهٔ فیلترِ بخشِ ۳ را برایش بگذار. هدف این نیست که کد بگیری؛ این است که نگاشتِ بینِ دو شکل را ببینی. بعد خودت نتیجه را اجرا کن و با خروجیِ اصلی مقایسه کن.

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

کلمه تلفظ به حروف فارسی یعنی چه
for / while فور / وایل دو شکلِ حلقه: روی یک مجموعه، یا تا وقتی شرطی برقرار است
range رِینج تولیدکنندهٔ بازهٔ عددی؛ از صفر تا قبل از عددِ داده‌شده
enumerate اینیومِرِیت همزمان شماره و عنصر را می‌دهد
accumulator اَکیومیولِیتور متغیری که قبل از حلقه ساخته می‌شود و در حلقه پُر
break / continue بریک / کانتینیو خروج از حلقه / پریدن به دورِ بعد
list comprehension لیست کامپری‌هِنشِن شکلِ یک‌خطیِ ساختنِ فهرست از یک حلقه

تمرین‌ها

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

در فصل بعد#

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

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

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