فصل ۳: کنترل جریان — تصمیم‌گیری و تکرار

حلقه‌ها: while، for، range و break/continue/else

تکرار، قلب اتوماسیون

پایتون دو حلقه دارد: while که «تا وقتی شرط درست است» تکرار می‌کند، و for که «روی اعضای یک مجموعه» می‌چرخد. قاعده‌ی انتخاب ساده است: اگر تعداد یا مجموعه‌ی اعضا را می‌دانید، for؛ اگر پایان به رویدادی بستگی دارد (ورودی درست کاربر، رسیدن به هدف)، while.

while و اعتبارسنجی ورودی

while True:
    text = input("تعداد تخته (۱ تا ۱۰۰): ")
    if text.isdigit() and 1 <= int(text) <= 100:
        qty = int(text)
        break                     # خروج از حلقه
    print("عدد معتبر وارد کنید.")

print(f"{qty} تخته ثبت شد")

الگوی while True + break رایج‌ترین راه برای «تا ورودی درست نیامده، دوباره بپرس» است. اگر حلقه‌ای بی‌پایان شد، در ترمینال Ctrl+C آن را متوقف می‌کند.

عملگر walrus

از Python 3.8 عملگر := اجازه می‌دهد وسط یک عبارت، مقداری را به متغیر نسبت دهید. برای حلقه‌هایی که ورودی می‌خوانند بسیار تمیز است:

while (cmd := input("> ").strip()) != "q":
    print(f"دستور: {cmd}")

for و range

for روی هر چیز «پیمایش‌پذیر» (iterable) کار می‌کند: لیست، رشته، دیکشنری، فایل و… . برای تکرار عددی از range استفاده می‌شود که عدد پایانی را شامل نمی‌شود:

عبارتاعداد تولیدشده
range(5)0, 1, 2, 3, 4
range(1, 6)1, 2, 3, 4, 5
range(0, 20, 5)0, 5, 10, 15
range(10, 0, -3)10, 7, 4, 1
prices = [8_500_000, 12_000_000, 4_200_000]
total = 0
for p in prices:
    if p < 5_000_000:
        continue              # این یکی را رد کن و برو سراغ بعدی
    total += p
print(f"{total:,}")           # 20,500,000

else روی حلقه: کمترشناخته‌شده اما مفید

حلقه‌های for و while می‌توانند بخش else داشته باشند که فقط اگر حلقه بدون break تمام شود اجرا می‌شود. کاربرد کلاسیک: جست‌وجو.

codes = ["KSH-101", "TBZ-220", "MSH-310"]
target = "ISF-500"

for code in codes:
    if code == target:
        print("پیدا شد")
        break
else:
    print("سفارشی با این کد وجود ندارد")

بدون else باید یک متغیر پرچم (found = False) تعریف می‌کردید. نام else این‌جا کمی گمراه‌کننده است؛ آن را در ذهن «nobreak» بخوانید.

نکته‌هایی که کمتر کسی می‌داند

  • متغیر حلقه‌ی for بعد از حلقه باقی می‌ماند و آخرین مقدار را دارد؛ اما اگر حلقه اصلاً اجرا نشود (لیست خالی)، تعریف نشده است و NameError می‌گیرید.
  • حذف عضو از لیستی که روی آن for می‌زنید، عضوها را جا می‌اندازد. روی یک کپی بچرخید (for x in items[:]:) یا لیست جدید بسازید.
  • range لیست نمی‌سازد و حافظه‌ی ثابتی دارد؛ range(10**12) فوری ساخته می‌شود و 10**11 in range(10**12) هم بدون پیمایش جواب می‌دهد.
  • break فقط از درونی‌ترین حلقه خارج می‌شود؛ برای خروج از دو حلقه‌ی تودرتو، آن‌ها را در یک تابع بگذارید و return کنید.
  • برای شمارش معکوس، reversed(range(5)) خواناتر از range(4, -1, -1) است و خطای یکی‌کم‌یکی‌زیاد ندارد.

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.