পাঠ ০৪ · ২৫-এর মধ্যে · মডিউল ১

if/else ও loop

Conditionals & loops — control flow
৬ মিনিট পড়া শুরু · Beginner ব্রাউজারে কোড চালান

এই পাঠে যা শিখবেন

  • if/elif/else — শর্তসাপেক্ষ logic
  • for loop — sequence ও range-এ iterate
  • while loop — শর্ত-ভিত্তিক loop
  • break, continue, else clause — control transfer
  • Nested loop ও indentation-এর গুরুত্ব

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

Programming-এ "যদি … তাহলে …" — সবচেয়ে মৌলিক control structure। Python-এ এটি if keyword দিয়ে।

তিন অংশের কাঠামো

১) if condition: — শর্ত সত্য হলে।
২) elif condition: — আগেরটা মিথ্যা, এটা সত্য হলে। (যত খুশি)
৩) else: — কোনোটা না মিললে। (ঐচ্ছিক)

Python
# গ্রেড নির্ণয়
score = 78

if score >= 80:
    grade = "A+"
elif score >= 70:
    grade = "A"
elif score >= 60:
    grade = "A-"
elif score >= 50:
    grade = "B"
else:
    grade = "F"

print(f"Score: {score}, Grade: {grade}")

    
Python indentation-sensitive — block বোঝাতে ৪-space (বা tab)। C/Java-এর {} নেই। ভুল indent → IndentationError।

২ · Truthy ও Falsy — Python-এর "সত্য" কী?

Python
# Falsy values — if-এ False হিসেবে ধরা হয়
falsy_examples = [False, 0, 0.0, "", [], {}, None]

for item in falsy_examples:
    if item:
        print(f"{repr(item)} → truthy")
    else:
        print(f"{repr(item)} → falsy")

# Pythonic check
data = []
if not data:                # খালি list = falsy
    print("কোনো ডেটা নেই")

    
if data: — Pythonic style। if len(data) > 0: বলার দরকার নেই। খালি collection নিজেই falsy।

৩ · for loop — sequence-এ iterate

Python-এর for "C-এর for"-এর মতো নয় — এটি iteratorIteratorএকটি object যা একে একে item দিতে পারে। __next__ method আছে। For loop নিজেই iterator-এর উপর চলে। Memory efficient — পুরোটা একসাথে নয়।-ভিত্তিক — for-each।

Python
# list-এ iterate
fruits = ["আম", "জাম", "কাঁঠাল"]
for fruit in fruits:
    print(f"আমি {fruit} খাই")

# range — সংখ্যা সিরিজ
for i in range(5):              # 0, 1, 2, 3, 4
    print(i, end=" ")
print()

for i in range(2, 10, 2):       # 2, 4, 6, 8 (start, stop, step)
    print(i, end=" ")
print()

# enumerate — index ও value একসাথে
for idx, fruit in enumerate(fruits):
    print(f"{idx}: {fruit}")

    
range(stop), range(start, stop), range(start, stop, step) — তিন রূপ। AI-তে epoch loop, batch index — সর্বত্র।

৪ · while loop — শর্ত-ভিত্তিক

Python
# Loss-এর simulation — যতক্ষণ না threshold-এ পৌঁছে
loss = 1.0
epoch = 0
threshold = 0.01

while loss > threshold:
    loss = loss * 0.7              # ধীরে কমে
    epoch += 1
    print(f"Epoch {epoch}: loss={loss:.4f}")

print(f"\nthreshold-এ পৌঁছাতে {epoch} epoch লাগল")

    
Infinite loop সাবধান! while-এর শর্ত কখনো বদলায় না — তাহলে কখনো শেষ হবে না। AI-তে training loop-এ max_epoch safety net সবসময় রাখুন।

৫ · break ও continue

Python
# break — loop থামাও
print("=== break demo ===")
for n in range(20):
    if n == 5:
        break                # খুঁজে পেয়েছি, আর দরকার নেই
    print(n, end=" ")
print()

# continue — পরের iteration-এ যাও
print("=== continue demo ===")
for n in range(10):
    if n % 2 == 0:
        continue             # জোড় skip
    print(n, end=" ")        # 1 3 5 7 9
print()

    
কোড কীভাবে flow করে if vs for vs while 🔀 if/elif/else condition True False block A else block পরের কোড 🔁 for loop item ∈ items? আছে body loop নেই loop শেষ ♻️ while loop condition? True body False loop শেষ break = জোর করে বের, continue = পরের iteration-এ লাফ
Branch + iterate — যেকোনো algorithm-এর দু'টি মূল উপাদান। AI training loop = এই দু'টোর মিশ্রণ।

৬ · Nested loop

Python
# গুণের নামতা — 2x2
for i in range(1, 4):
    for j in range(1, 4):
        print(f"{i}×{j}={i*j:2d}", end="  ")
    print()      # প্রতি row-এর শেষে newline

    
Nested loop = বাড়ির প্রতি তলার প্রতি ফ্ল্যাট। বাইরের loop "তলা", ভিতরের "ফ্ল্যাট"। AI-তে — outer = epoch, inner = batch।

৭ · AI-তে loop-এর প্রয়োগ

Python
# Mini training loop — pseudo
n_epochs = 5
batches = ["b1", "b2", "b3"]

for epoch in range(1, n_epochs + 1):
    epoch_loss = 0
    for batch in batches:
        # forward, backward, update — pseudo
        batch_loss = 1.0 / (epoch + 1)     # demo decay
        epoch_loss += batch_loss
    avg = epoch_loss / len(batches)
    print(f"Epoch {epoch}: avg_loss={avg:.4f}")

    # early stopping
    if avg < 0.2:
        print("যথেষ্ট ভাল — training থামাও")
        break

    
প্রতিটি AI training-এর কঙ্কাল এই কাঠামো: বাইরের epoch loop, ভিতরের batch loop, threshold-এ break। L-15 থেকে আমরা এর বাস্তবিক রূপ দেখব।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ Python-এ {} না — indentation দিয়ে block। কেন এই radical সিদ্ধান্ত? এর সুবিধা ও ঝুঁকি কী? AI কোডের পঠনযোগ্যতার সাথে এর সম্পর্ক?

Indentation-as-syntax — Python-এর সবচেয়ে polarizing design choice। Guido van Rossum ১৯৯১-এ এই সিদ্ধান্ত নেন — programming history-তে যা বিরল।

Guido-র যুক্তি:

  • "Code is read 10× more than written" — পঠনযোগ্যতা প্রথম priority।
  • C/Java-এ — programmer এমনিতেও indent করে। তাহলে compiler কেন কেয়ার করে না?
  • Indent ও {} mismatch — confusing bug source।
  • "There should be one obvious way to do it" — Zen of Python।

সুবিধা:

  • Visual ও syntactic structure সবসময় match।
  • কোড dense নয় — air ও spacing।
  • Diff ছোট — bracket লাইন থাকে না।
  • Beginner-friendly — কম symbol।

ঝুঁকি ও সমস্যা:

  • Tab/space mixing: Python ৩-এ illegal, কিন্তু legacy code-এ চলে।
  • Copy-paste subtle bug: editor-এ indent বদলে গেলে behavior বদলায়।
  • Email/chat-এ code paste: indentation চলে যায়।
  • Multi-line lambda অসম্ভব — single line-এ আটকে।
  • Auto-formatting tool কঠিন: "correct" indent কী — context-নির্ভর।

Tooling-এর সমাধান:

  • Black: opinionated formatter — সবার কোড একই দেখায়।
  • ruff: ১০০× দ্রুত linter+formatter (Rust-এ লেখা)।
  • EditorConfig: team-wide editor settings।
  • pre-commit hooks: push-এর আগে auto-format।

AI কোডে এর তাৎপর্য:

  • Notebook cell-এ paste করে "running" — indent ভুল কামড় দেয়।
  • Deep nested model code — visual structure কোড পড়া সহজ করে।
  • Stack Overflow থেকে copy — সবসময় re-indent।
  • Jupyter-এ shift+tab indent helpful।

অন্য language-এ এই philosophy:

  • Haskell, F# — optional indent-based syntax।
  • YAML — pure indent-based (controversial)।
  • Go — tab-only enforced।
  • Rust — formatter rustfmt enforced।

মূল উপলব্ধি: Indent = visual contract। ভাল IDE + Black = সমস্যা শেষ। Beginners-এর জন্য awkward, পেশাদারদের জন্য liberation। Python = "executable pseudocode"-এর spirit এই indent-এ।

প্র ০২ "Loop ব্যবহার এড়িয়ে চল — vectorize কর" — AI/ML-এ কেন এই pure mantra? Python-এ for loop এত ধীর কেন? GPU-এর সাথে এর সম্পর্ক কী?

Vectorization — AI performance-এর সবচেয়ে গুরুত্বপূর্ণ একক ধারণা। এটা না বুঝলে — production AI কোড impossible।

Python for loop কেন ধীর?

  • প্রতি iteration-এ Python interpreter overhead — bytecode dispatch, type checking।
  • প্রতি element-এ object allocation/dereference।
  • GIL (Global Interpreter Lock) — multi-thread parallelism নেই।
  • CPython implementation — JIT নেই (PyPy-তে আছে)।

Vectorization কী?

  • Operation একটি element-এ নয়, পুরো array-এ একসাথে।
  • NumPy a + b — Python loop নয়, C-তে SIMD instruction।
  • GPU-তে — হাজার core parallel।

Concrete benchmark:

# ১ লক্ষ float-এর square
# Python loop:
result = []
for x in data:
    result.append(x * x)
# 50 ms

# NumPy vectorized:
result = data ** 2
# 0.5 ms — ১০০× দ্রুত

# GPU (PyTorch):
result = data.cuda() ** 2
# 0.05 ms — ১০০০× দ্রুত

SIMD-এর জাদু:

  • "Single Instruction, Multiple Data" — একটি CPU instruction ৪/৮/১৬টি float একসাথে।
  • AVX-512 — ১৬ float একসাথে (Intel Skylake+)।
  • GPU SIMT — হাজার thread।

কখন loop ঠিক আছে?

  • Loop-এর body-তে I/O (file, network) — bottleneck Python নয়।
  • Sequential dependency — RNN unrolling।
  • Small data — overhead worth it নয়।
  • Outer training loop — epoch ৫০, vectorize-এর কিছু নেই।

Vectorization-এর প্যাটার্ন:

  • Replace explicit loop: [x*2 for x in lst] → arr * 2।
  • Broadcasting: shape mismatch auto-resolve।
  • Boolean masking: arr[arr > 0] — filter without loop।
  • Reduction: arr.sum(), arr.mean()।

"Numpy thinking" — paradigm shift:

  • প্রশ্ন: "প্রতিটি element-এর জন্য কী করব?" — wrong।
  • প্রশ্ন: "পুরো array-কে কোন function-এ পাঠাব?" — right।
  • Brain-এর reflex বদল — সময় লাগে।

মূল উপলব্ধি: Loop = কম্পিউটারের natural language। Vectorize = mathematician-এর natural language। AI = math-heavy → vectorize default। L09–L12-এ NumPy-তে এই thinking তৈরি হবে।

প্র ০৩ Python-এ for loop-এর সাথে else clause আছে — অদ্ভুত feature। কখন কাজে লাগে? Real AI কোডে এর প্রয়োগ কোথায়?

Python-এর for-else — সবচেয়ে confusing feature, কিন্তু চমৎকার pattern।

Behavior: for/while loop normally complete (break ছাড়া) হলে else block চলে।

for x in data:
    if x == target:
        print("পাওয়া গেছে")
        break
else:
    print("নেই")    # break না হলে এই block

Why "else"? — name বিভ্রান্তিকর:

  • Knuth-এর মতে এটি "nobreak" বলা উচিত ছিল।
  • "else" অর্থ — "if you didn't break"।
  • Guido নিজে এটি পছন্দ নাম স্বীকার করেছেন।

সাধারণ pattern — search:

# খারাপ — flag variable
found = False
for x in data:
    if x == target:
        found = True
        break
if not found:
    handle_missing()

# ভাল — for/else
for x in data:
    if x == target:
        process(x)
        break
else:
    handle_missing()

AI কোডে কাজের examples:

  • Convergence check:
    for epoch in range(max_epochs):
        train_one_epoch()
        if loss < threshold:
            print(f"Converged at epoch {epoch}")
            break
    else:
        print("Did not converge")    # max_epochs শেষ
  • Hyperparameter search:
    for lr in lr_grid:
        if try_train(lr) > 0.95:
            best_lr = lr
            break
    else:
        raise ValueError("কোনো learning rate কাজ করেনি")
  • Validation:
    for sample in batch:
        if not validate(sample):
            raise ValueError(f"Invalid: {sample}")
            break
    else:
        proceed_to_train()

সমালোচনা:

  • অপরিচিতদের জন্য বিভ্রান্তিকর।
  • Code review-এ comment ছাড়া পড়া কঠিন।
  • অনেক senior dev এড়িয়ে চলেন।

Alternatives:

  • Function + early return:
    def find(target, data):
        for x in data:
            if x == target:
                return x
        return None
  • সাধারণত — function-এ wrap করা cleaner।

মূল উপলব্ধি: for-else exotic কিন্তু powerful। জানা থাকলে — "did the loop finish without break?" pattern এক structure-এ। আজকের preference — function-এ encapsulate, কিন্তু legacy কোড পড়তে এই knowledge দরকার।

প্র ০৪ Conditional logic বেশি হলে — if/elif chain কুৎসিত হয়। Python 3.10-এ match/case এসেছে। Strategy pattern, dict dispatch — alternatives কী কী? কখন কোনটা?

Branching logic বাড়লে — কোড maintainability ভেঙে পড়ে। Modern Python-এ এর কয়েকটি সুন্দর pattern আছে।

সমস্যার রূপ:

# ১০টি case — কুৎসিত
def get_optimizer(name):
    if name == "sgd":
        return SGD(...)
    elif name == "adam":
        return Adam(...)
    elif name == "rmsprop":
        return RMSprop(...)
    # ... আরও

সমাধান ১: Dict dispatch (Pythonic):

OPTIMIZERS = {
    "sgd": SGD,
    "adam": Adam,
    "rmsprop": RMSprop,
}

def get_optimizer(name, **kwargs):
    cls = OPTIMIZERS.get(name)
    if cls is None:
        raise ValueError(f"Unknown: {name}")
    return cls(**kwargs)
  • O(1) lookup। Extensible — নতুন entry শুধু dict-এ।
  • Test data-driven।
  • Plugin architecture-এর ভিত্তি।

সমাধান ২: match/case (Python 3.10+, ২০২১):

def parse_command(cmd):
    match cmd:
        case ["train", model, *args]:
            train(model, args)
        case ["predict", model, input]:
            predict(model, input)
        case ["save", path]:
            save(path)
        case _:
            raise ValueError("Unknown command")
  • Structural pattern matching — Rust/Haskell-এর মতো।
  • Destructuring + condition একসাথে।
  • Complex data structure-এর জন্য আদর্শ।

সমাধান ৩: Strategy pattern (OO):

class Strategy:
    def execute(self, x): ...

class FastStrategy(Strategy):
    def execute(self, x): return x * 2

class SafeStrategy(Strategy):
    def execute(self, x): return x
  • Strategy ভিন্ন ভিন্ন behavior একই interface-এ।
  • Heavy কাজ, configurable।

সমাধান ৪: Polymorphism (duck typing):

  • Python "if isinstance(x, ...)" এড়াও।
  • Object-এর method call — type ignore।

AI-তে concrete:

  • Model registry: Hugging Face Transformers — model name string → class।
  • Loss function: "mse"/"crossentropy"/"focal" → callable।
  • Activation: "relu"/"gelu"/"silu" → torch function।
  • Data augmentation: recipe → list of operations।

কখন কোনটা — guideline:

  • ২-৩টি case → simple if/elif।
  • ৪-১০টি case → dict dispatch।
  • Pattern matching, destructuring → match/case।
  • Complex behavior → Strategy class।
  • Deep type hierarchy → polymorphism।

"Replace conditional with polymorphism" — Martin Fowler:

  • Refactoring book-এর famous pattern।
  • OOP দিয়ে if/else explosion দূর।

মূল উপলব্ধি: If/elif chain — code smell। ১০-এর বেশি — refactor। AI ML codebase-এ — registry pattern + dict dispatch + match/case = clean architecture। L05-এ function ও lambda — এই idiom-এর বিল্ডিং ব্লক।

অনুশীলন

  1. FizzBuzz: 1 থেকে 15 print করুন। কিন্তু — ৩-এর গুণিতকে "Fizz", ৫-এর গুণিতকে "Buzz", দু'টোর গুণিতকে "FizzBuzz"।
    for n in range(1, 16):
        if n % 15 == 0:
            print("FizzBuzz")
        elif n % 3 == 0:
            print("Fizz")
        elif n % 5 == 0:
            print("Buzz")
        else:
            print(n)

    মনে রাখুন — ১৫-এর check আগে। নাহলে "Fizz" বা "Buzz" দিয়ে শেষ হয়ে যাবে।

  2. Factorial: ৬-এর factorial (১×২×৩×৪×৫×৬) loop দিয়ে হিসাব করুন।
    result = 1
    for i in range(1, 7):
        result *= i
    print(f"6! = {result}")    # 720
  3. সর্বোচ্চ খুঁজুন: একটি list-এ সবচেয়ে বড় সংখ্যা loop দিয়ে বের করুন (built-in max ছাড়া)।
    nums = [12, 45, 7, 89, 23, 56, 34]
    biggest = nums[0]
    for n in nums[1:]:
        if n > biggest:
            biggest = n
    print(f"সর্বোচ্চ: {biggest}")    # 89

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

কোড রানার কাজ না করলে? ব্রাউজারে কাজ না করলে Google Colab ব্যবহার করুন।
পূর্ববর্তী পাঠ
পাঠ ০৩ · List, Tuple ও Dictionary