الفصل 09

اتخاذ القرارات — if و elif و else

سلوك مسارات مختلفة بناءً على الشروط، لماذا يُعد التنسيق والمسافات البادئة ذا معنى في بايثون، والخطأ الخفي الذي يحدث عند ترتيب الشروط بشكل خاطئ.

35 دقيقةPython 3.12
  1. 1المشكلة
  2. 2الفهم
  3. 3أمثلة محلولة
  4. 4التوقع
  5. 5التطبيق
  6. 6التحدي

المشكلة التي نقوم بحلها

في الدرس السابق تعلمنا كيف نطرح الأسئلة — مثل هل age >= 18 صحيحة أم خاطئة؟ ولكن البرنامج لم يفعل شيئاً بتلك الإجابة سوى طباعة True أو False.

حان الوقت الآن للتصرف بناءً على تلك الإجابة. مسار يُتبع إذا تحقق الشرط، ومسار آخر إذا لم يتحقق. هذه هي اللحظة التي يتوقف فيها الكود عن كونه مجرد قائمة خطوات خطية ويبدأ في اتخاذ القرارات.

وهنا يختلف بايثون عن العديد من اللغات الأخرى: فالأسطر التي تتبع شرطاً معيناً وتلك التي تقع خارجه تتحدد بواسطة المسافات البادئة (Indentation). لا توجد أقواس معقوفة {}. قد يبدو الأمر غريباً في البداية ولكنك ستعتاد عليه وسيعجبك — لأن الكود الذي يبدو منظماً هو كود منظم بالفعل.

في نهاية هذا الدرس ستكون قادراً على

  • تنفيذ الكود شرطياً باستخدام if
  • تقديم خيار بديل باستخدام else وعدة خيارات باستخدام elif
  • تطبيق المسافات البادئة بشكل صحيح وقراءة وحل خطأ IndentationError
  • فهم سبب أهمية ترتيب الشروط — وهو الفخ الأكبر في هذا الدرس
  • تداخل الشروط (Nesting) ومعرفة متى تتجنبه

المتطلبات السابقة: True و False — تعلّم طرح الأسئلة.


أبسط صورة للجملة الشرطية

python
age = 22

if age >= 18:
    print("You may enter")

print("Program finished")
text
You may enter
Program finished

يتكون هذا الهيكل من ثلاثة أجزاء:

  1. الكلمة المفتاحية if، تليها العبارة الشرطية
  2. النقطتان الرأسيتان : في نهاية سطر الشرط — نسيانهما هو الخطأ الأكثر شيوعاً
  3. الأسطر التالية، وتكون مُزاحة بأربع مسافات بادئة — هذه الأسطر المُزاحة هي التي يحكمها الشرط

لو كانت قيمة age تساوي 15، فلن يُنفّذ أمر print الأول، بينما سيُنفّذ الأخير دائماً — لأنه يقع خارج نطاق الشرط.

المسافة البادئة تعني المعنى البرمجي

هذان البرنامجان يتطابقان تقريباً في الأحرف ولكن سلوكهما مختلف تماماً:

python
score = 30

if score >= 50:
    print("Passed")
    print("Certificate issued")

عند تشغيل هذا الكود، لن يظهر أي شيء في الطرفية — لأن كلا السطرين يقعان داخل نطاق الشرط، والشرط غير متحقّق.

python
score = 30

if score >= 50:
    print("Passed")
print("Certificate issued")
text
Certificate issued

سطر print الثاني أصبح الآن خارج نطاق الشرط، لذا سيُنفّذ دائماً — وتم إصدار شهادة لشخص رسب في الاختبار! سطر واحد أُزيح بشكل خاطئ يكسر منطق العمل بالكامل، دون أن يُصدر بايثون أي خطأ لأن كلا البرنامجين صحيحان نحوياً.

استخدم 4 مسافات، وتجنب زر Tab. يقبل بايثون كلاً منهما، ولكن خلطهما في ملف واحد يسبب خطأ TabError. في محرر VS Code، الضغط على Tab يقوم تلقائياً بإدراج 4 مسافات مسطرة.

else — المسار البديل

python
age = 15

if age >= 18:
    print("You may enter")
else:
    print("Sorry, adults only")
text
Sorry, adults only

لا تحمل else أي شرط، لأن معناها الضمني هو: "إذا لم يتحقق أي شرط مما سبق".

elif — تعدد المسارات والخيارات

python
marks = 72

if marks >= 80:
    grade = "A"
elif marks >= 70:
    grade = "B"
elif marks >= 60:
    grade = "C"
elif marks >= 40:
    grade = "D"
else:
    grade = "F"

print(f"Marks {marks} gives grade {grade}")
text
Marks 72 gives grade B

elif اختصار لـ "else if" (وإلا إذا). ما يحدث هو أن بايثون يتفقد الشروط بالترتيب من الأعلى إلى الأسفل، ويُنفّذ كتلة أول شرط يتحقق ثم يخرج فوراً من السلسلة الشرطية بالكامل دون فحص باقي الشروط.

وهنا الفخ الأكبر في الشروط

نظراً لأن elif تتوقف عند أول شرط يتحقق، فإن كتابة الشروط بترتيب خاطئ تؤدي لبرنامج يعمل دون أخطاء ولكنه يعطي نتائج غير صحيحة:

python
marks = 95

if marks >= 40:
    grade = "Pass"
elif marks >= 80:
    grade = "Excellent"
else:
    grade = "Fail"

print(grade)
text
Pass

حصل الطالب على 95 درجة ولم يحصل على Excellent! لأن الشرط 95 >= 40 تحقق فوراً، فتوقف بايثون عنده ولم ينظر إلى الشرط الثاني إطلاقاً.

القاعدة الذهبية: ضع الشرط الأكثر دقة وتحديداً أولاً، والشرط الأوسع والأشمل في النهاية.

تداخل الشروط (Nesting)

python
is_logged_in = True
is_admin = False

if is_logged_in:
    if is_admin:
        print("Welcome, admin")
    else:
        print("Welcome, user")
else:
    print("Please log in")
text
Welcome, user

يمكن في كثير من الأحيان تبسيط ذلك باستخدام المعامل and:

python
is_logged_in = True
is_admin = False

if is_logged_in and is_admin:
    print("Welcome, admin")
elif is_logged_in:
    print("Welcome, user")
else:
    print("Please log in")
text
Welcome, user

مثال عملي متكامل

ملف fare.py:

python
# Work out a ticket fare from age and day of week
age = int(input("Passenger age : "))
day = input("Day of week   : ").strip().lower()

base_fare = 120.0

# Most specific rule first, loosest last
if age < 5:
    fare = 0.0
    category = "Infant"
elif age < 18:
    fare = base_fare * 0.5
    category = "Child"
elif age >= 60:
    fare = base_fare * 0.7
    category = "Senior"
else:
    fare = base_fare
    category = "Adult"

is_weekend = day == "saturday" or day == "sunday"
if is_weekend:
    fare = fare * 1.2

print()
print(f"Category : {category}")
print(f"Weekend  : {is_weekend}")
print(f"Fare     : {fare:.2f}")
text
Passenger age : 65
Day of week   : Sunday

Category : Senior
Weekend  : True
Fare     : 100.80

حالات الخطأ الشائعة

SyntaxError: expected ':' نسيان النقطتين الرأسيتين في نهاية سطر if أو elif أو else.

IndentationError: expected an indented block after 'if' statement السطر الذي يلي if غير مُزاح بمسافة بادئة.

IndentationError: unexpected indent سطر مُزاح بمسافة بادئة دون أن يتبع لأي كتلة برمجية.

TabError: inconsistent use of tabs and spaces in indentation خلط مسافات المسطرة مع Tab داخل نفس الملف.