Intermediate24 minPrerequisite: Functions

Lambda, Recursion & Decorators

Functions ke advanced forms � quick lambda, tree recursion, aur power decorator pattern.

Advanced functions kyun seekhein?

Basic def se tumne functions banana shuru kiya. Ab teen powerful patterns hain jo code ko concise, reusable aur expressive banate hain:

  • Lambda � small tasks ke liye quick anonymous function
  • Recursion � tree traversal aur divide-and-conquer mein use hota hai
  • Decorator � functions ko modify karta hai bina unhe change kiye

In patterns ko samajhna chahta hai to concept grid dekho:

LAMBDA

lambda x: x*2 � anonymous function, kabhi kabhi named function likhne ki zaroorat nahi.

RECURSION

Function khud ko call karta hai � har call chhota hota hai jab tak base case na aaye.

DECORATOR

Function wrapper jo extra behavior add karta hai � logging, timing, authentication.

Lambda: anonymous function

Lambda ek small function hai jo bina naam ke hota hai. Jaise sticky note � ek kaam karo aur phek do.

lambda_basics.py
# Lambda � single expression
double = lambda x: x * 2
print(double(5)) # 10

# Lambda with map/filter
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # [1, 4, 9, 16, 25]

evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # [2, 4]

Lambda ka syntax: lambda parameters: expression. Ek hi expression hota hai, multiple lines nahi. map() har element par lambda apply karta hai, filter() sirf true wale rakhta hai.

Lambda kab use karein? Sorting mein key function, map/filter mein quick transformation, ya callback functions mein. Complex logic ho to named def function better hai.

Recursion: function khud ko call kare

Recursion mein function apne aap ko chhota version mein call karta hai. Har recursive call ke liye ek base case zaroori hai � warna infinite loop ho jayega.

recursion_examples.py
# Factorial: n! = n � (n-1)!
def factorial(n):
 if n <= 1: # base case
 return 1
 return n * factorial(n - 1) # recursive case

print(factorial(5)) # 120

# Fibonacci: 0, 1, 1, 2, 3, 5, 8...
def fibonacci(n):
 if n <= 0:
 return 0
 if n == 1:
 return 1
 return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(6)) # 8

Factorial example mein: factorial(5) calls 5 * factorial(4), jo calls 4 * factorial(3), aur aise chalta hai jab tak factorial(1) return 1 na kare � woh hai base case.

Stack overflow warning: Recursion mein har call ek stack frame leta hai. Bahut deep recursion se memory full ho sakti hai. Python mein default limit 1000 hai. Iterative solution zyada efficient hota hai jab recursion zaroori nahi.

Recursion real use-cases

Recursion tab useful hai jab problem naturally divide ho chhoti sub-problems mein:

recursion_practical.py
# Directory traversal (conceptual)
def count_files(folder):
 count = 0
 for item in folder:
 if item.is_file():
 count += 1
 elif item.is_dir():
 count += count_files(item) # recursive call
 return count

# Sum of list elements
def list_sum(nums):
 if len(nums) == 0:
 return 0
 return nums[0] + list_sum(nums[1:])

print(list_sum([1, 2, 3, 4, 5])) # 15

# Power calculation
def power(base, exp):
 if exp == 0:
 return 1
 return base * power(base, exp - 1)

print(power(2, 10)) # 1024

Har example mein pattern same hai: base case check karo, warna chhoti problem solve karo aur result jodo.

Decorator: function ka wrapper

Decorator ek function hai jo doosre function ko leta hai, usme kuch add karta hai, aur naya wrapped function return karta hai. @ syntax se use hota hai.

decorator_basics.py
# Timer decorator
def timer(func):
 import time
 def wrapper(*args, **kwargs):
 start = time.time()
 result = func(*args, **kwargs)
 end = time.time()
 print(f"{func.__name__} took {end-start:.4f}s")
 return result
 return wrapper

@timer
def slow_function():
 import time
 time.sleep(0.1)
 return "done"

print(slow_function())

@timer exactly same hai jaise slow_function = timer(slow_function). Wrapper function call karne par pehle timer start hota hai, phir original function run hota hai, phir time print hota hai.

Decorators ke real examples

decorator_examples.py
# Logger decorator
def logger(func):
 def wrapper(*args, **kwargs):
 print(f"Calling {func.__name__} with {args}, {kwargs}")
 result = func(*args, **kwargs)
 print(f"{func.__name__} returned {result}")
 return result
 return wrapper

@logger
def add(a, b):
 return a + b

add(3, 5)
# Output:
# Calling add with (3, 5), {}
# add returned 8

# Cache decorator (memoization)
def cache(func):
 memo = {}
 def wrapper(*args):
 if args not in memo:
 memo[args] = func(*args)
 return memo[args]
 return wrapper

@cache
def fibonacci(n):
 if n <= 0:
 return 0
 if n == 1:
 return 1
 return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(50)) # Instant! Without cache bahut slow hota

Decorators se tumhe function ke andar logging, caching, ya authentication jaise cross-cutting concerns milte hain bina business logic change kiye.

Concept grid: quick recap

LAMBDA

lambda x: x*2 � quick anonymous function, map/filter mein use karo.

RECURSION

Function khud ko call kare � base case zaroori hai, tree/graph problems mein best.

DECORATOR

@decorator se function ko wrap karo � logging, timing, caching add karo.

Try it: Lambda sorting & RecursionCode edit karo aur Run dabao
Run Python dabayein

Quick check

Lambda function likho jo number ka square kare.

lambda keyword, ek parameter, colon, aur expression x**2 ya x*x.

Common mistakes

Advanced function patterns complete?

Great. Ab list comprehension, generators aur context managers dekho � aur bhi Pythonic patterns seekho.