برنامه‌نویسی پایتون فهرست مطالب
فصل ۵

elif و شرط‌های تودرتو

دنیای واقعی دو حالته نیست. نمره دانش‌آموز چهار درجه دارد، منوی برنامه پنج گزینه، و روزهای هفته هفت تا. این فصل درباره انتخاب از میان چند حالت است.

در این فصل می‌خوانید
  1. دستور elif
  2. فقط اولین شاخه درست اجرا می‌شود
  3. ترتیب شاخه‌ها مهم است
  4. ماشین‌حساب
  5. شرط تودرتو
  6. elif یا تودرتو، کدام
  7. عملگر شرطی یک‌خطی
  8. دستور match
  9. منو با match
  10. یک برنامه کوچک ترکیبی

۱. دستور elif

کلمه elif کوتاه‌شده else if است، یعنی «وگرنه اگر». با آن می‌شود هر تعداد شاخه پشت سر هم گذاشت.

# 'elif' means "else if". Python tests the branches from top to bottom and
# runs ONLY the first one whose condition is True.
user_input = input('Enter a number (1-7): ')

if user_input == '1':
    print('Shanbe')
elif user_input == '2':
    print('Yekshanbe')
elif user_input == '3':
    print('Doshanbe')
elif user_input == '4':
    print('Seshanbe')
elif user_input == '5':
    print('Chaharshanbe')
elif user_input == '6':
    print('Panjshanbe')
elif user_input == '7':
    print('Jome')
else:
    print('Error: the number must be between 1 and 7')

روز هفته: نمونه 01_elif_days.py

Enter a number (1-7): 3
Doshanbe

شرح مثال

۲. فقط اولین شاخه درست اجرا می‌شود

این مهم‌ترین قانون elif است. پایتون شرط‌ها را از بالا به پایین امتحان می‌کند و به محض اینکه یکی درست شد، بلوکش را اجرا می‌کند و بقیه را کاملاً نادیده می‌گیرد.

# Three possible outcomes -> if / elif / else.
user_input = input('Enter a number: ')
number = float(user_input)

if number > 0:
    print('Positive')
elif number < 0:
    print('Negative')
else:
    print('Zero')

مثبت، منفی یا صفر: نمونه 02_elif_sign.py

فرق سه if جدا با if و دو elif

اگر سه if جداگانه بنویسید، پایتون هر سه را بررسی می‌کند و ممکن است چند تایشان اجرا شوند. با elif فقط یکی اجرا می‌شود و بقیه حتی بررسی هم نمی‌شوند. وقتی حالت‌ها متقابلاً ناسازگارند (عدد نمی‌تواند هم مثبت باشد هم منفی)، همیشه elif درست‌تر و سریع‌تر است.

۳. ترتیب شاخه‌ها مهم است

# The ORDER of the branches matters. We test from the highest score downwards,
# so when we reach 'elif score >= 17' we already know the score is below 20.
user_input = input('Enter the score (0-20): ')
score = float(user_input)

if score > 20 or score < 0:
    print('Invalid score')
elif score >= 17:
    print('A - Excellent')
elif score >= 14:
    print('B - Good')
elif score >= 10:
    print('C - Passed')
else:
    print('F - Failed')

نمره به حرف: نمونه 03_elif_grades.py

شرح مثال

۴. ماشین‌حساب

این مثال هم elif دارد و هم یک if تودرتو، و نمونه خوبی است از اینکه هر دو ابزار در یک برنامه کنار هم می‌نشینند.

# A simple calculator: two numbers and one operator.
num1 = float(input('Enter number 1: '))
num2 = float(input('Enter number 2: '))

operator = input('Enter the sign (+ - * / **): ')

if operator == '+':
    result = num1 + num2
    print(result)
elif operator == '-':
    result = num1 - num2
    print(result)
elif operator == '*':
    result = num1 * num2
    print(result)
elif operator == '/':
    # Dividing by zero would crash the program, so we check it first.
    if num2 == 0:
        print('Error: division by zero!')
    else:
        result = num1 / num2
        print(result)
elif operator == '**':
    result = num1 ** num2
    print(result)
else:
    print('Error: unknown operator!')

ماشین‌حساب: نمونه 04_calculator.py

Enter number 1: 8
Enter number 2: 0
Enter the sign (+ - * / **): /
Error: division by zero!
باگی که در نسخه اصلی این برنامه بود

در فایل اصلی دوره، بررسی تقسیم بر صفر وجود نداشت. اگر کاربر مخرج را صفر می‌داد، برنامه با خطای ZeroDivisionError کاملاً متوقف می‌شد. قانون کلی: هر جا تقسیم دارید، به مخرج صفر فکر کنید. این یکی از سه چهار خطایی است که در تمام دنیا برنامه‌ها را از کار می‌اندازد.

۵. شرط تودرتو

شرط تودرتو یعنی یک if داخل بلوک یک if دیگر. وقتی به کار می‌آید که سؤال دوم فقط در صورتی معنا دارد که جواب سؤال اول مثبت باشد.

# A nested 'if' is an 'if' placed inside the block of another 'if'.
# Here the password is only asked about when the username is correct.
username = input('Enter the username: ')
password = input('Enter the password: ')

if username == 'admin':
    if password == '123456':
        print('Welcome', username)
    else:
        print('The password is incorrect!')
else:
    print('The username is incorrect!')

ورود تودرتو: نمونه 05_nested_login.py

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

# Same program, but the password is only READ when the username is correct.
# This is the real advantage of nesting: we skip work we do not need.
USERNAME = 'admin'
PASSWORD = '123456'

username_input = input('Enter username: ')

if username_input == USERNAME:
    password_input = input('Enter password: ')

    if password_input == PASSWORD:
        print('Welcome!')
    else:
        print('Password error!')
else:
    print('Username error!')

ورود تودرتو، نسخه دوم: نمونه 06_nested_login2.py

شرح مثال

نکته امنیتی

جالب است بدانید سایت‌های واقعی عمداً برعکس این کار را می‌کنند و همیشه پیام یکسان «نام کاربری یا رمز اشتباه است» می‌دهند. اگر برنامه بگوید «نام کاربری اشتباه است»، مهاجم می‌فهمد کدام نام‌های کاربری وجود دارند و نصف کار را انجام داده است.

۶. elif یا تودرتو، کدام

حالتابزار درستمثال
چند حالت هم‌رده و ناسازگارelifروز هفته، نمره، منو
سؤال دوم وابسته به جواب سؤال اولتودرتواول نام کاربری، بعد رمز

قانون عملی: اگر تودرتویی از سه سطح بیشتر شد، معمولاً یعنی طراحی را باید عوض کرد. کد عمیقاً تودرتو خوانده نمی‌شود. در فصل یازدهم با تابع و در فصل هشتم با continue راه‌هایی برای صاف کردن این تودرتویی‌ها می‌بینید.

۷. عملگر شرطی یک‌خطی

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

# When an if/else only chooses between two VALUES, Python offers a one-line form:
#     value_if_true if condition else value_if_false
age = int(input('Enter your age: '))

status = 'adult' if age >= 18 else 'minor'
print(status)

# The long version does exactly the same thing:
if age >= 18:
    status = 'adult'
else:
    status = 'minor'
print(status)

# It is often used directly inside a print():
number = 7
print(f'{number} is', 'even' if number % 2 == 0 else 'odd')

عملگر شرطی: نمونه 08_ternary.py

Enter your age: 20
adult
adult
7 is odd

شرح مثال

۸. دستور match

از پایتون ۳٫۱۰ به بعد، ساختار تازه‌ای اضافه شده که وقتی همه شاخه‌ها یک مقدار واحد را با چیزهای مختلف مقایسه می‌کنند، تمیزتر از زنجیره elif است.

# From Python 3.10 on, 'match ... case' is a clean alternative to a long
# chain of elif branches that all compare the SAME value.
user_input = input('Enter a number (1-7): ')

match user_input:
    case '1':
        print('Shanbe')
    case '2':
        print('Yekshanbe')
    case '3':
        print('Doshanbe')
    case '4':
        print('Seshanbe')
    case '5':
        print('Chaharshanbe')
    case '6' | '7':          # '|' means "or": one branch for two values
        print('Weekend')
    case _:                  # '_' is the default branch, like 'else'
        print('Error: the number must be between 1 and 7')

روز هفته با match: نمونه 09_match_days.py

شرح مثال

۹. منو با match

# A menu is the classic use of match/case.
print('1) New file')
print('2) Open file')
print('3) Save file')
print('0) Exit')

choice = input('Enter the number: ')

match choice:
    case '1':
        print('Creating a new file...')
    case '2':
        print('Opening a file...')
    case '3':
        print('Saving the file...')
    case '0':
        print('Goodbye!')
    case _:
        print('Unknown option.')

منو: نمونه 10_match_menu.py

منو کلاسیک‌ترین کاربرد match است. فعلاً این برنامه یک بار اجرا می‌شود و تمام. در فصل هشتم آن را داخل یک حلقه while می‌گذاریم تا منو تا وقتی کاربر گزینه خروج را نزده تکرار شود، و آن وقت تازه شبیه یک برنامه واقعی می‌شود.

۱۰. یک برنامه کوچک ترکیبی

# If the number is odd, make it even by adding 1, then print its square.
user_input = input('Please enter a number: ')
number = int(user_input)

if number % 2 != 0:
    number += 1

result = number ** 2
print('Result:', result)

زوج کردن و توان دو: نمونه 11_make_it_even.py

Please enter a number: 7
Result: 64

اینجا if بدون else آمده است و کاملاً درست است. وقتی عدد زوج باشد، هیچ کاری ضرورتی ندارد. این الگو، یعنی «اگر لازم بود اصلاحش کن و بعد ادامه بده»، در برنامه‌های واقعی بسیار دیده می‌شود.

فایل‌های تمرینی این فصل

پوشه S05-elif-and-nested-conditionals شامل نمونه‌های 01_elif_days.py تا 11_make_it_even.py.

خلاصه فصل

ابزاروظیفه آن
elifشاخه بعدی. هر تعداد که بخواهید
ترتیب شاخه‌هافقط اولین شاخه درست اجرا می‌شود، پس ترتیب حیاتی است
else پایانیگرفتن حالت‌های پیش‌بینی‌نشده. تقریباً همیشه بنویسیدش
شرط تودرتووقتی سؤال دوم فقط با جواب مثبت سؤال اول معنا دارد
a if cond else bانتخاب یک‌خطی بین دو مقدار
match و caseجایگزین تمیز زنجیره elif وقتی همه یک متغیر را می‌سنجند
case _:شاخه پیش‌فرض در match
تقسیم بر صفرهر جا تقسیم هست، مخرج صفر را بررسی کنید

تمرین‌های فصل پنج

  1. شماره ماه (۱ تا ۱۲) را بگیرید و بگویید مربوط به کدام فصل است.
  2. یک نمره بگیرید و با elif حرف معادلش را چاپ کنید.
  3. یک منوی چهار گزینه‌ای بنویسید و به هر گزینه واکنش نشان دهید. از match استفاده کنید.
  4. وزن و قد را بگیرید، شاخص توده بدنی را با weight / height ** 2 حساب کنید و دسته‌اش را بگویید: زیر ۱۸٫۵، بین ۱۸٫۵ و ۲۵، بین ۲۵ و ۳۰، بالای ۳۰.
  5. سه عدد بگیرید و از کوچک به بزرگ مرتب چاپشان کنید، فقط با if و elif و else.
  6. ماشین‌حساب را طوری کامل کنید که % و // را هم پشتیبانی کند.
  7. تمرین اول فصل چهار را با عملگر شرطی یک‌خطی بازنویسی کنید.
  8. یک کاراکتر بگیرید و بگویید حرف صدادار است، بی‌صداست یا رقم.
فصل قبل: شرط‌ها فصل بعد: حلقه for