کنترل جریان

شرط در پایتون: if، elif، else و شرط‌های تودرتو

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

تا اینجا برنامه‌ها خط به خط از بالا به پایین اجرا می‌شدند. اما برنامهٔ واقعی باید تصمیم بگیرد: اگر رمز درست بود وارد شو، وگرنه خطا بده. ساده‌ترین دستور انشعاب (branching) دستور شرطی است که سه بخش دارد:

  1. یک تست: عبارتی که نتیجه‌اش True یا False است.
  2. یک بلوک کد که اگر تست درست بود اجرا شود.
  3. یک بلوک اختیاری که اگر تست نادرست بود اجرا شود.
          ┌──────┐
          │ کد   │
          └──┬───┘
             ▼
         ◇ تست ◇
       True    False
        ▼        ▼
   بلوک True  بلوک False
        └───┬────┘
            ▼
          ┌──────┐
          │ ادامه │
          └──────┘

if و else

x = int(input("Enter an integer: "))
if x % 2 == 0:
    print("")
    print("Even")
else:
    print("")
    print("Odd")
print("Done with conditional")

دقت کنید:

  • بعد از شرط و بعد از else دونقطه (:) می‌آید.
  • خطوط داخل هر بلوک تورفتگی (indentation) دارند. در پایتون تورفتگی بخشی از دستور زبان است، نه فقط زیبایی. پایتون از روی تورفتگی می‌فهمد کدام خطوط مال کدام بلوک‌اند.
  • خط آخر تورفتگی ندارد، پس بیرون از if/else است و در هر صورت اجرا می‌شود.

💡 استاندارد پایتون برای هر سطح تورفتگی ۴ فاصله است. ویرایشگرها با زدن Tab خودشان ۴ فاصله می‌گذارند. هیچ‌وقت تب و فاصله را در یک فایل قاطی نکنید.

else اختیاری است. اگر نباشد و شرط نادرست باشد، پایتون بی‌سروصدا از روی بلوک رد می‌شود.

elif: چند حالت

وقتی بیش از دو حالت داریم، از elif (مخفف else if) استفاده می‌کنیم:

a = 200
b = 33
if b > a:
    print("b is greater than a")
elif a == b:
    print("a and b are equal")
else:
    print("a is greater than b")

پایتون شرط‌ها را به ترتیب بررسی می‌کند و فقط اولین شرطی که درست باشد اجرا می‌شود؛ بقیه دیگر بررسی نمی‌شوند. else آخر هم شرطی ندارد: «اگر هیچ‌کدام نبود».

if <condition>:
    <expressions>
elif <condition>:
    <expressions>
else:
    <expressions>

شرط تودرتو

داخل یک بلوک if می‌شود یک if دیگر نوشت (با یک سطح تورفتگی بیشتر):

x = 12
if x % 2 == 0:
    if x % 3 == 0:
        print("Divisible by 2 and 3")
    else:
        print("Divisible by 2 and not by 3")
elif x % 3 == 0:
    print("Divisible by 3 and not by 2")

چرا برای حالت فرد، else و داخلش یک if دیگر ننوشتیم؟ چون اگر به elif برسیم، مطمئنیم عدد فرد است (وگرنه وارد if اول شده بود). پس فقط کافی است بخش‌پذیری بر ۳ را بررسی کنیم. خط کمتر، منطق یکسان.

ترکیب شرط‌ها با and و or

x, y, z = 8, 3, 5
if x < y and x < z:
    print("x is least")
elif y < z:
    print("y is least")
else:
    print("z is least")

باز هم دقت کنید: وقتی به elif می‌رسیم، می‌دانیم x کوچک‌ترین نیست. پس فقط کافی است y و z را مقایسه کنیم.

مسئله: مرتب کردن سه عدد

برنامه‌ای بنویسید که سه عدد بگیرد و آن‌ها را از کوچک به بزرگ چاپ کند.

این مسئلهٔ ساده نشان می‌دهد که برای یک مسئله چند راه‌حل با کیفیت‌های خیلی متفاوت وجود دارد.

راه‌حل ۱: همهٔ حالت‌ها با elif

سه عدد ۶ ترتیب ممکن دارند؛ می‌شود همه را نوشت:

a = int(input("عدد وارد کن: "))
b = int(input("عدد وارد کن: "))
c = int(input("عدد وارد کن: "))

if a < b < c:
    print(a, b, c)
elif a < c < b:
    print(a, c, b)
elif b < a < c:
    print(b, a, c)
elif b < c < a:
    print(b, c, a)
elif c < a < b:
    print(c, a, b)
elif c < b < a:
    print(c, b, a)
else:
    print("حداقل دو تا مساوی‌اند")

کار می‌کند، ولی طولانی است و حالت‌های مساوی را هم درست مرتب نمی‌کند.

راه‌حل ۲: شرط تودرتو

با هر مقایسه، نیمی از حالت‌ها حذف می‌شوند:

a = int(input("a: "))
b = int(input("b: "))
c = int(input("c: "))

if a < b:
    if b < c:
        print(a, b, c)
    elif a < c:
        print(a, c, b)
    else:
        print(c, a, b)
else:
    if a < c:
        print(b, a, c)
    elif b < c:
        print(b, c, a)
    else:
        print(c, b, a)

در بدترین حالت فقط سه مقایسه انجام می‌شود و اعداد مساوی هم درست مرتب می‌شوند.

راه‌حل ۳: جابه‌جا کردن متغیرها

ایدهٔ هوشمندانه‌تر: به‌جای چاپ مستقیم، مقدار متغیرها را آن‌قدر جابه‌جا کنیم تا همیشه a ≤ b ≤ c شود:

a = int(input("a: "))
b = int(input("b: "))
c = int(input("c: "))

if a > b:
    a, b = b, a     # حالا a کوچک‌ترِ a و b است
if a > c:
    a, c = c, a     # حالا a کوچک‌ترین هر سه است
if b > c:
    b, c = c, b     # و b از c کوچک‌تر

print(a, b, c)

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

💡 در عمل، پایتون برای مرتب‌سازی تابع آماده دارد: print(sorted([a, b, c])). ولی فکر کردن به این راه‌حل‌ها همان چیزی است که شما را برنامه‌نویس می‌کند.

تمرین

۱. کوچک‌ترین عدد

سه عدد بگیرید و فقط کوچک‌ترین را چاپ کنید (بدون sorted و min).

جواب
a = int(input("a: "))
b = int(input("b: "))
c = int(input("c: "))

if a < b and a < c:
    print("a کوچک‌ترین است:", a)
elif b < c:
    print("b کوچک‌ترین است:", b)
else:
    print("c کوچک‌ترین است:", c)

۲. سال کبیسه (میلادی)

سالی کبیسه است که بر ۴ بخش‌پذیر باشد، مگر اینکه بر ۱۰۰ بخش‌پذیر باشد؛ ولی اگر بر ۴۰۰ بخش‌پذیر باشد، باز هم کبیسه است. برنامه‌ای بنویسید که یک سال بگیرد و بگوید کبیسه است یا نه. با ۲۰۲۴ (کبیسه)، ۱۹۰۰ (نه) و ۲۰۰۰ (کبیسه) تست کنید.

جواب
year = int(input("سال: "))
if year % 400 == 0:
    print("کبیسه")
elif year % 100 == 0:
    print("کبیسه نیست")
elif year % 4 == 0:
    print("کبیسه")
else:
    print("کبیسه نیست")

یا در یک خط: (year % 4 == 0 and year % 100 != 0) or year % 400 == 0