অধ্যায় 09

সিদ্ধান্ত নেওয়া — if, elif, else

শর্ত দেখে আলাদা পথে যাওয়া, ইনডেন্টেশন কেন পাইথনে অর্থ বহন করে, আর শর্তের ক্রম ভুল হলে যে নীরব বাগটা তৈরি হয়।

35 মিনিটPython 3.12
  1. 1সমস্যা
  2. 2বোঝা
  3. 3উদাহরণ
  4. 4অনুমান
  5. 5নিজে করা
  6. 6কঠিন করা

যে সমস্যাটা আমরা সমাধান করছি

আগের মিশনে আমরা প্রশ্ন করা শিখেছি — age >= 18 সত্য না মিথ্যা। কিন্তু উত্তর জেনে প্রোগ্রাম কিছুই করছিল না, শুধু True বা False ছেপে দিচ্ছিল।

এখন সেই উত্তরটা কাজে লাগানোর সময়। শর্ত সত্য হলে এক পথ, মিথ্যা হলে আরেক পথ। এটাই প্রোগ্রামিংয়ের সেই মুহূর্ত যেখানে কোড আর সরল তালিকা থাকে না — সে সিদ্ধান্ত নিতে শুরু করে।

আর পাইথনে একটা জিনিস অন্য অনেক ভাষার চেয়ে আলাদা: কোন লাইনগুলো শর্তের ভেতরে আর কোনগুলো বাইরে, সেটা ঠিক হয় ফাঁকা জায়গা দিয়ে। বাঁকা বন্ধনী নেই। প্রথমে অস্বস্তি লাগে, তারপর ভালো লাগতে শুরু করে — কারণ যে কোডটা দেখতে গোছানো, সেটাই আসলে গোছানো।

এই মিশন শেষে আপনি পারবেন

  • if দিয়ে শর্তসাপেক্ষে কোড চালাতে
  • else দিয়ে বিকল্প পথ দিতে, আর elif দিয়ে একাধিক পথ
  • ইনডেন্টেশন ঠিকভাবে লিখতে, আর IndentationError পড়ে সমাধান করতে
  • শর্তের ক্রম কেন গুরুত্বপূর্ণ তা বুঝতে — এখানেই সবচেয়ে বড় ফাঁদ
  • শর্তের ভেতরে আরেকটা শর্ত বসাতে, আর কখন সেটা এড়াতে হবে তা বুঝতে

আগে যা জানা লাগবে: 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 চলত না, কিন্তু শেষ 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-টা এখন শর্তের বাইরে, তাই সে সব সময় চলে — এমনকি যে ফেল করেছে তার নামেও সার্টিফিকেট ছাপা হয়ে গেল। এক লাইনের ইনডেন্টেশন ভুল হলে ব্যবসার নিয়মটাই ভেঙে যায়, আর পাইথন কোনো ত্রুটি দেয় না — দুটোই বৈধ কোড।

চার স্পেস, ট্যাব নয়। পাইথন দুটোই মানে, কিন্তু একই ফাইলে দুটো মিশিয়ে ফেললে TabError আসে, আর সেটা খুঁজে বের করা কষ্টকর কারণ চোখে ট্যাব আর স্পেস একই রকম দেখায়। VS Code-এ ট্যাব চাপলে সে চার স্পেস বসিয়ে দেয় — এই সেটিংটাই সবাই ব্যবহার করে, আর এটাই পাইথনের সরকারি রীতি।

else — অন্য পথ

python
age = 15

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

else-এর সাথে কোনো শর্ত থাকে না, কারণ তার শর্তটা আগেই বলা হয়ে গেছে — "উপরের কোনোটাই সত্য না হলে"। if আর 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 মানে "নাহলে যদি"। এখানে যা ঘটে তা হলো — পাইথন উপর থেকে নিচে যায়, প্রথম যে শর্তটা সত্য পায় সেটার কাজ করে, তারপর পুরো শিকলটা ছেড়ে বেরিয়ে যায়। বাকি শর্তগুলো পরীক্ষা করেও দেখে না।

marks = 72 হলে: 72 >= 80 মিথ্যা, 72 >= 70 সত্য → grade = "B", আর শেষ। 72 >= 60 আর 72 >= 40 সত্য হলেও সেগুলো আর দেখাই হয় না।

এখানেই সবচেয়ে বড় ফাঁদ

elif "প্রথম সত্যটাতেই থামে" — এই একটা কথার ফল হলো, শর্তের ক্রম ভুল হলে প্রোগ্রাম চলে, ত্রুটি দেয় না, শুধু ভুল উত্তর দেয়:

python
marks = 95

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

print(grade)
text
Pass

৯৫ পেয়েও Excellent আসেনি। কারণ 95 >= 40 প্রথমেই সত্য হয়ে গেছে, আর পাইথন সেখানেই থেমে গেছে — দ্বিতীয় শর্তটা কখনো পরীক্ষা করাই হয়নি।

নিয়মটা মনে রাখুন: সবচেয়ে কঠিন বা সবচেয়ে নির্দিষ্ট শর্তটা আগে লিখুন, সবচেয়ে ঢিলেটা শেষে। সংখ্যার সীমা নিয়ে কাজ করলে বড় থেকে ছোটর দিকে নামুন, যেমন উপরের গ্রেডের উদাহরণে।

এই বাগটা এতই নীরব যে চোখে দেখা ছাড়া ধরার উপায় নেই। তাই শর্তের শিকল লেখার পর অভ্যাস করুন — প্রতিটি ধাপের জন্য একটা করে মান দিয়ে চালিয়ে দেখা। উপরের গ্রেডের কোডটা 95, 72, 65, 45 আর 20 — পাঁচটা মান দিয়ে চালালে পাঁচটা আলাদা উত্তর আসা উচিত। একটাও না মিললে ক্রমে সমস্যা।

শর্তের ভেতরে শর্ত

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

ভেতরের if-টা আট স্পেস ভেতরে, কারণ সে বাইরের if-এর অধীনে। এটা কাজ করে, কিন্তু ধাপ যত বাড়ে কোড পড়া তত কঠিন হয়। অনেক সময় 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

দুটোর কোনটা ভালো তা নির্ভর করে কোনটা পড়তে সহজ লাগে তার উপর। তিন ধাপের বেশি ভেতরে ঢুকে গেলে থামুন আর নতুন করে ভাবুন — সেটা প্রায় সব সময়ই ইঙ্গিত যে শর্তগুলো অন্যভাবে সাজানো যায়।

ইনপুট যাচাই করা

এখন আমাদের হাতে সেই হাতিয়ারটা আছে, যা দিয়ে আগের মিশনের ঝুলে থাকা সমস্যাটার সমাধান করা যায় — ব্যবহারকারী কিছুই না লিখলে বা শব্দ লিখলে কী হবে:

python
raw = input("Your age: ").strip()

if raw == "":
    print("You did not type anything")
elif raw.isdigit():
    age = int(raw)
    if age >= 18:
        print(f"Age {age}: you may enter")
    else:
        print(f"Age {age}: adults only")
else:
    print(f"'{raw}' is not a whole number")
text
Your age: twenty
'twenty' is not a whole number

isdigit() একটা নতুন মেথড — লেখার সব অক্ষর সংখ্যা কি না বলে। এটাই int()-এ পাঠানোর আগে যাচাই করার সহজ উপায়, আর এতে ValueError আর আসে না। (isdigit() ঋণাত্মক সংখ্যা বা দশমিক মানে না — সেগুলোর জন্য পরে try শেখা লাগবে।)


একটা সম্পূর্ণ উদাহরণ

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

দুটো নকশার সিদ্ধান্ত লক্ষ্য করুন। এক, বয়সের শর্তগুলো elif দিয়ে জোড়া, কারণ একজন যাত্রী ঠিক একটা শ্রেণিতেই পড়বেন। দুই, সাপ্তাহিক ছুটির শর্তটা আলাদা if, কারণ সেটা স্বাধীন প্রশ্ন — বয়স যাই হোক, ছুটির দিনের বাড়তি ভাড়া আলাদাভাবে যোগ হয়। কোনটা elif আর কোনটা আলাদা if, এই সিদ্ধান্তটাই শর্ত লেখার আসল কাজ।


কিছু ভাঙা অবস্থা ও তার সমাধান

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 একই ফাইলে ট্যাব আর স্পেস মেশানো হয়েছে। সম্পাদকে "convert indentation to spaces" চালিয়ে দিন।

SyntaxError — elif বা else একা দাঁড়িয়ে আছে elif আর else সব সময় একটা if-এর সাথে থাকে, আর তার ইনডেন্টেশন ওই if-এর সমান হতে হয়।

TypeError: '>=' not supported between instances of 'str' and 'int' input()-এর মান বদলাতে ভুলে গেছেন। int(input(...)) লিখুন।

শর্ত ঠিক লাগছে কিন্তু ভুল পথে যাচ্ছে ক্রম দেখুন। ঢিলে শর্ত আগে থাকলে কঠিন শর্তটা কখনো পরীক্ষাই হয় না। প্রতিটি শাখার জন্য একটা করে মান দিয়ে চালিয়ে দেখুন।