Recursion মানে একটা function একই সমস্যার একটা ছোট version দিয়ে নিজেকে call করে সমস্যা সমাধান করে, যতক্ষণ না এটা সরাসরি উত্তর দেওয়ার মতো যথেষ্ট সহজ একটা version-এ পৌঁছায়।
def factorial(n):
if n <= 1:
return 1 # base case — recursion থামায়
return n * factorial(n - 1) # recursive case
factorial(5) # 5 * 4 * 3 * 2 * 1 = 120def count_down(n):
# base case নেই — এটা নিজে থেকে কখনো থামে না
print(n)
count_down(n - 1)
# count_down(5) শেষ পর্যন্ত raise করে:
# RecursionError: maximum recursion depth exceededসবচেয়ে common recursion bug
প্রতিটা recursive function-এর সত্যিকারভাবে পৌঁছানো যায় এমন একটা base case দরকার — কখনো trigger না হওয়া একটা base case কোনো base case না থাকার মতোই একই রকম ব্যর্থ হয়।
কিছু ভাষার মতো না, Python একটা recursive call chain কতটা গভীর যেতে পারে তার উপর একটা default limit (সাধারণত ১০০০) প্রয়োগ করে, specifically interpreter crash করার আগে runaway recursion ধরার জন্য।
import sys
print(sys.getrecursionlimit()) # default-এ 1000
# এটা বাড়ানো সম্ভব কিন্তু কমই সঠিক সমাধান —
# এর মানে সাধারণত সমস্যাটা এর বদলে একটা loop দিয়ে সমাধান করা উচিত
sys.setrecursionlimit(3000)def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
[fibonacci(i) for i in range(8)]
# [0, 1, 1, 2, 3, 5, 8, 13]| Recursion | একটা Loop |
|---|---|
| স্বাভাবিকভাবে recursive একটা সমস্যার জন্য (একটা tree traverse করা, nested data) প্রায়ই বেশি স্বাভাবিক দেখায় | একটা সহজ repeated কাজের জন্য সাধারণত দ্রুত আর কম memory ব্যবহার করে |
| প্রতিটা call একটা call stack frame যোগ করে — গভীর recursion Python-এর recursion limit-এ পৌঁছাতে পারে | যত iteration-ই হোক না কেন কোনো stack depth উদ্বেগ নেই |
Recursive function-এর জন্য একটা আসল optimization
উপরের Fibonacci উদাহরণ একই মান বারবার আবার হিসাব করে — ছোট input-এর পরে সত্যিকারভাবে ধীর। আগের Decorators lesson থেকে @functools.lru_cache decorator প্রথমবার হিসাব হওয়ার সময় প্রতিটা ফলাফল cache করে এই নির্দিষ্ট সমস্যা ঠিক করে।