کنترل جریان

حلقهٔ for و range در پایتون؛ break و continue

۴ دقیقه مطالعه · به‌روزرسانی ۲۲ مهر ۱۴۰۵

خیلی وقت‌ها با حلقه می‌خواهیم بشماریم: ۰ تا ۹، ۱۰ تا ۱۰۰ ده‌تا‌ده‌تا، یا روی تک‌تک حروف یک کلمه. با while باید سه جای مختلف را مدیریت کنیم (مقدار اولیه، شرط، افزایش). for همهٔ این‌ها را در یک خط خلاصه می‌کند:

# با while
n = 0
while n < 5:
    print(n)
    n = n + 1
# همان کار با for
for n in range(5):
    print(n)

ساختار for

for <متغیر> in <دنباله>:
    <دستورها>
  • در هر دور، <متغیر> یک مقدار از دنباله می‌گیرد؛
  • بار اول اولین مقدار، دفعهٔ بعد مقدار بعدی، و همین‌طور تا آخر؛
  • بدنهٔ حلقه هر بار با مقدار جدید اجرا می‌شود.

دیگر لازم نیست خودتان متغیر را زیاد کنید، پس حلقهٔ بی‌نهایت تصادفی هم نخواهید داشت.

تابع range

range(شروع, توقف, گام)
  • مقدار پیش‌فرض شروع ۰ و گام ۱ است و می‌شود ننوشتشان.
  • شمارش تا یکی قبل از توقف ادامه پیدا می‌کند. خود توقف جزو نتیجه نیست؛ همان قانون برش رشته‌ها.
print(list(range(5)))          # [0, 1, 2, 3, 4]
print(list(range(3, 10)))      # [3, 4, 5, 6, 7, 8, 9]
print(list(range(3, 10, 2)))   # [3, 5, 7, 9]
print(list(range(10, 101, 10)))
print(list(range(10, 1, -2)))  # گام منفی: شمارش معکوس

(اینجا list فقط برای این است که همهٔ مقدارها را یکجا ببینیم.)

💡 range(5) واقعاً یک فهرست ۵ عددی در حافظه نمی‌سازد؛ هر عدد را همان لحظه‌ای که لازم است تولید می‌کند. برای همین range(1_000_000_000) هم تقریباً هیچ حافظه‌ای نمی‌گیرد. به این ویژگی «تنبل» (lazy) بودن می‌گویند. بعدها با generatorها بیشتر آشنا می‌شویم.

mysum = 0
for i in range(7, 10):
    mysum += i
print(mysum)   # 7 + 8 + 9 = 24
mysum = 0
for i in range(5, 11, 2):
    mysum += i
print(mysum)   # 5 + 7 + 9 = 21

حلقه روی رشته

for فقط روی اعداد کار نمی‌کند؛ روی هر دنباله‌ای می‌چرخد. مثلاً روی کاراکترهای یک رشته:

for ch in "salam":
    print(ch)

این بسیار پرکاربرد است و در درس متدهای رشته مفصل‌تر می‌بینیمش.

break: خروج فوری از حلقه

break بلافاصله از حلقه بیرون می‌آید و بقیهٔ دستورهای آن دور را هم اجرا نمی‌کند.

mysum = 0
for i in range(5, 11, 2):
    mysum += i
    if mysum == 5:
        break
print(mysum)

قبل از اجرا حدس بزنید خروجی چیست! (جواب: 5. در اولین دور mysum می‌شود ۵ و حلقه همان‌جا تمام می‌شود.)

اگر حلقه‌ها تودرتو باشند، break فقط از درونی‌ترین حلقه بیرون می‌آید:

while condition_1:
    while condition_2:
        expression_a
        break          # فقط از حلقهٔ درونی خارج می‌شود
        expression_b   # هیچ‌وقت اجرا نمی‌شود
    expression_c       # بعد از break اینجا ادامه پیدا می‌کند

continue: پریدن به دور بعد

continue بقیهٔ همین دور را رها می‌کند و سراغ دور بعدی می‌رود (از حلقه خارج نمی‌شود):

for i in range(1, 11):
    if i % 3 == 0:
        continue      # مضرب‌های ۳ را رد کن
    print(i, end=" ")

for یا while؟

for while
کاربرد وقتی تعداد دورها یا دنباله معلوم است وقتی فقط شرط توقف را می‌دانید
مثال ۱ تا ۱۰۰، هر حرف یک کلمه تا وقتی کاربر q نزده
حلقهٔ بی‌نهایت تصادفی تقریباً غیرممکن اگر متغیر را زیاد نکنید، بله

هر for را می‌شود با while نوشت (برعکسش همیشه ممکن نیست)، ولی وقتی چیزی را می‌شمارید، for کوتاه‌تر و امن‌تر است.

تمرین

۱. اعداد زوج

با for کدی بنویسید که خروجی‌اش این باشد:

2
4
6
8
10
Goodbye!
جواب
for i in range(2, 11, 2):
    print(i)
print("Goodbye!")

۲. شمارش معکوس

حالا این را:

Hello!
10
8
6
4
2
جواب
print("Hello!")
for i in range(10, 1, -2):
    print(i)

۳. هوپ!

اعداد ۰ تا ۵۰ را در یک خط و با * بین‌شان چاپ کنید، ولی به‌جای مضرب‌های ۵ کلمهٔ hop را بنویسید.

جواب
for i in range(51):
    if i % 5 == 0:
        print("hop", end="*")
    else:
        print(i, end="*")

یک نکتهٔ جالب: if not i % 5: هم همین کار را می‌کند. وقتی i % 5 صفر باشد، ارزش منطقی‌اش False است و not آن را True می‌کند. ولی نسخهٔ == 0 خواناتر است.

۴. جمع ۱ تا end

یک حلقهٔ for بنویسید که جمع اعداد ۱ تا end (با خود end) را حساب کند. مثلاً برای end = 6 جواب 21 است.

جواب
end = 6
total = 0
for i in range(1, end + 1):
    total += i
print(total)

دقت کنید: range(1, end) خود end را شامل نمی‌شود، برای همین end + 1 نوشتیم. این اشتباه «یکی کم/زیاد» (off-by-one) از رایج‌ترین باگ‌های دنیاست!