Function ও Lambda
এই পাঠে যা শিখবেন
- Function definition ও call —
def,return - Parameter ও argument — positional, keyword, default
- *args, **kwargs — variable arguments
- Lambda — এক লাইনের anonymous function
- Higher-order function: map, filter, sorted-এ key
- Scope ও closure-এর প্রাথমিক ধারণা
১ · Function কেন?
একই কাজ বার বার লিখলে — bug ৫× জায়গায়, fix-ও ৫× জায়গায়। FunctionFunctionইনপুট নিয়ে আউটপুট দেওয়া পুনর্ব্যবহারযোগ্য কোডব্লক। Python-এ def দিয়ে define। AI-তে activation, loss, optimizer — সবই function। এক জায়গায় — call হাজার জায়গায়। DRY: Don't Repeat Yourself।
১) def keyword + নাম।
২) Parameter list — input।
৩) Body (indented) — কাজের ধাপ।
৪) return — output (ঐচ্ছিক, default None)।
# Function define
def square(x):
"""একটি সংখ্যার বর্গ ফিরিয়ে দেয়।"""
return x * x
def greet(name, greeting="শুভ সকাল"):
"""default argument সহ।"""
return f"{greeting}, {name}!"
# Call
print(square(5)) # 25
print(square(2.5)) # 6.25
print(greet("রহিম")) # default
print(greet("ফাতেমা", "নমস্কার"))
"""…""" = docstringDocstringFunction/class-এর ভেতরে প্রথম string — documentation। help(func)-এ দেখায়। AI library-তে standard। — function-এর ব্যাখ্যা। help(square) বা IDE hover-এ দেখাবে।
২ · Positional ও Keyword arguments
def train(model, lr, epochs=10, verbose=True):
return f"{model} trained with lr={lr}, {epochs} epochs"
# Positional — ক্রম গুরুত্বপূর্ণ
print(train("BERT", 0.001))
# Keyword — clarity, ক্রম free
print(train(model="GPT", lr=0.0001, epochs=20))
# Mixed — positional আগে
print(train("ResNet", 0.01, verbose=False))
train(model, lr=..., epochs=..., batch_size=...)। Keyword-এ স্পষ্টতা — readability প্রথম priority।
৩ · *args ও **kwargs — flexible signature
# *args — variable positional
def total(*nums):
return sum(nums)
print(total(1, 2, 3)) # 6
print(total(1, 2, 3, 4, 5)) # 15
# **kwargs — variable keyword
def configure(**settings):
for key, value in settings.items():
print(f" {key} = {value}")
configure(lr=0.001, batch=32, optimizer="adam")
# একসাথে
def model_fit(X, y, *, epochs=10, **extra):
print(f"Training on {len(X)} samples")
print(f"Epochs: {epochs}")
print(f"Extra: {extra}")
model_fit([1,2,3], [0,1,0], epochs=5, lr=0.01, dropout=0.2)
*args tuple-এ collect, **kwargs dict-এ। * single asterisk এর পরে সব argument keyword-only। PyTorch/TensorFlow API-তে এই pattern সর্বত্র।
৪ · Lambda — তাৎক্ষণিক ছোট function
LambdaLambdaAnonymous function — নাম ছাড়াই, এক expression-এ। Alonzo Church-র lambda calculus (১৯৩০) থেকে নাম। Python-এ lambda args: expr। — যখন ছোট function তাৎক্ষণিক দরকার, পুরো def overkill।
# def
def double(x):
return x * 2
# একই — lambda
double_l = lambda x: x * 2
print(double(5), double_l(5)) # 10 10
# multi-arg lambda
add = lambda a, b: a + b
print(add(3, 4)) # 7
# sorted-এ key — Pythonic
students = [("রহিম", 85), ("ফাতেমা", 92), ("করিম", 78)]
by_score = sorted(students, key=lambda s: s[1], reverse=True)
print(by_score)
if, for, multi-line — যাবে না। জটিল কাজ হলে — def ব্যবহার করুন। নাম দিন, docstring দিন।
৫ · Higher-order function — function-কে data হিসেবে
Python-এ function "first-class citizen" — variable-এ রাখা যায়, list-এ ঢোকানো যায়, function-এ পাঠানো যায়। এটাই AI-র optimizer/loss callback-এর ভিত্তি।
# Function variable-এ
def relu(x):
return max(0, x)
activation = relu # function পাস
print(activation(-3), activation(7)) # 0 7
# map — সব element-এ function apply
nums = [-2, -1, 0, 1, 2]
relu_out = list(map(relu, nums))
print(relu_out) # [0, 0, 0, 1, 2]
# filter — শর্ত মেলে এমন
positives = list(filter(lambda x: x > 0, nums))
print(positives) # [1, 2]
# function return করা
def make_multiplier(n):
def inner(x):
return x * n
return inner
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5), triple(5)) # 10 15
make_multiplier-এর ভেতরের inner outer-এর n "মনে রাখে" — এটাই closureClosureএকটি function যা enclosing scope-এর variable মনে রাখে। JavaScript ও Python উভয়ে আছে। Decorator-এর ভিত্তি। AI-তে stateful callback তৈরিতে।।
৬ · Scope — variable কোথায় বাঁচে?
x = 10 # global
def show():
y = 5 # local — শুধু এই function-এ
print(f"local y = {y}, global x = {x}")
show()
print(x)
# print(y) # NameError — local দেখা যাবে না
def modify():
global x
x = 100 # global x বদলে
modify()
print(x) # 100
global ব্যবহার এড়িয়ে চলুন — function-কে impure বানায়, test কঠিন। বদলে — argument পাঠান, return করুন।
৭ · AI-তে function-এর প্রয়োগ
- Activation: ReLU, sigmoid, tanh — সব function।
- Loss: MSE, cross-entropy — function যা y_true, y_pred নেয়।
- Optimizer step: SGD, Adam — gradient → update function।
- Data transform: normalize, augment — preprocessing function।
- Model: PyTorch
nn.Module-এরforward()= function। - Callback: on_epoch_end, on_batch_end — Keras/Lightning।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ "Pure function" বলতে কী বোঝায়? Functional programming-এর এই ধারণা AI/ML-এ কেন গুরুত্বপূর্ণ — testing, parallel, reproducibility-র দৃষ্টিতে?
Pure function — functional programming-এর soul। Side-effect-এর বিরুদ্ধে discipline।
Pure function-এর দু'টি শর্ত:
- Same input → same output (deterministic)।
- No side-effect — global state পরিবর্তন নেই, file/network/print নেই।
উদাহরণ:
# Pure
def add(a, b):
return a + b
# Impure — side effect
counter = 0
def add_with_log(a, b):
global counter
counter += 1
print(f"Call #{counter}")
return a + b
Pure function-এর সুবিধা:
- Testing সহজ: input দিলে output predictable। mock-এর দরকার নেই।
- Parallelizable: shared state নেই → race condition নেই।
- Memoizable: input → output cache করা যায়।
- Composable:
f(g(h(x)))safe। - Reasoning সহজ: "এই function এই input-এ কী করবে?" — predict possible।
AI/ML-এ এর তাৎপর্য:
- Reproducibility: impure code → run-to-run different। ML paper-এ disaster।
- Distributed training: Spark, Ray, JAX — pure function জরুরি।
- JAX-এর JIT: pure function compile করে XLA-তে। Impure → silent bug।
- Auto-differentiation: gradient হিসাব pure function ছাড়া meaningful নয়।
ML-এ অপরিহার্য impurity:
- Logging — print, MLflow।
- Random seed — সঠিকভাবে seed control করা।
- GPU state — tensor moves, memory allocation।
- File I/O — checkpoint save।
সমাধান — boundary-তে impurity:
- "Functional core, imperative shell" — Gary Bernhardt।
- Computation pure, I/O outside।
- Unit test pure core। Integration test shell।
Random এর কী হবে?
# Impure — hidden state
def augment(image):
return image + np.random.randn() # ভিন্ন run, ভিন্ন result
# Pure — explicit randomness
def augment(image, rng):
return image + rng.randn()
JAX এই philosophy-র champion — explicit PRNG key।
Side-effect-এর তালিকা:
- Global variable মুটেট।
- Argument mutate (list.append)।
- File/network/db read/write।
- print, logging।
- Time, random — hidden input।
- Exception raise (debatable)।
মূল উপলব্ধি: 100% pure code unrealistic। কিন্তু purity discipline = 90% bug elimination। AI engineer-এর জন্য — function-কে pure যথাসম্ভব রাখুন। Impurity boundary-তে contained। JAX-এর rise এই philosophy-র victory।
প্র ০২
Python-এ "mutable default argument" একটি কুখ্যাত bug source। def f(x=[]): কেন বিপজ্জনক? এই pitfall AI কোডে কীভাবে প্রকাশ পায়?
এই bug — Python-এর সবচেয়ে famous gotcha। প্রায় সব Python developer একবার করেছে। বুঝলে — চিরকাল বাঁচা।
সমস্যা:
def append_item(item, target=[]):
target.append(item)
return target
print(append_item("a")) # ['a']
print(append_item("b")) # ['a', 'b'] — কেন?!
print(append_item("c")) # ['a', 'b', 'c']
কারণ:
- Default argument function definition-এর সময় একবার evaluate হয়।
- Function object-এর সাথে bind — পরের call-এ একই list।
- Mutable হলে — append/modify shared।
সঠিক সমাধান — Sentinel pattern:
def append_item(item, target=None):
if target is None:
target = []
target.append(item)
return target
AI কোডে এর প্রকাশ:
# খারাপ — একই config sharing
def train_model(name, history={}):
history[name] = {"loss": []}
return history
train_model("BERT")
train_model("GPT") # BERT-এর history-ও সাথে!
- Hyperparameter dict: default mutable → পুরনো run-এর leak।
- Cache dict: function-call-এ cache shared (অনিচ্ছাকৃত)।
- List of metrics: training run-এ data leak।
- NumPy array default: একই reference, modification carry over।
কখন intentional?
- Memoization (
functools.lru_cacheভাল)। - Singleton state — global-এর alternative। Anti-pattern।
Type-checker সাহায্য:
- mypy/pyright warn — mutable default detect।
- ruff
B006rule — auto-detect। - CI-তে এই lint চালান।
Default best practices:
- Mutable default →
None+ body-তে check। - Immutable (int, str, tuple, frozenset) → safe।
- Type hint:
list[int] | None = None
একটি advanced trick — frozen default:
from types import MappingProxyType
DEFAULT_CFG = MappingProxyType({"lr": 0.001})
def train(cfg=DEFAULT_CFG):
# cfg.update(...) # ← TypeError, immutable
new_cfg = {**cfg, "epochs": 10} # safe
মূল উপলব্ধি: Mutable default = time bomb। প্রথমবার কাজ করে, পরে কামড় দেয়। AI-তে — config, history, cache — খুব common surface। Sentinel pattern + linter = সমাধান।
প্র ০৩ Lambda বনাম regular function — কখন কোনটা? "Lambda-কে variable-এ assign করা" কেন anti-pattern? Real AI কোডে lambda কোথায় idiomatic?
Lambda Python-এ controversial। PEP 8 সাবধানে style guide দেয়। ভালো ব্যবহার — শক্তি; বেশি ব্যবহার — অস্পষ্টতা।
Lambda-র সীমা:
- Single expression —
if/for/tryনেই (ternary OK)। - No statement — assignment, print নেই।
- Default name
<lambda>— stack trace-এ অস্পষ্ট। - No docstring।
Anti-pattern: lambda assign করা:
# খারাপ — PEP 8 violation
square = lambda x: x * x
# ভাল — def
def square(x):
return x * x
কেন? def name দেয়, traceback ভাল, debugger-এ ভাল, docstring লেখা যায়।
Lambda কোথায় idiomatic:
- sorted() key:
students.sort(key=lambda s: s.score) - map/filter:
(যদিও list comprehension প্রায় সবসময় ভাল)list(map(lambda x: x ** 2, nums)) - Pandas apply:
df["upper"] = df["name"].apply(lambda s: s.upper()) - GUI callback:
button.on_click(lambda: print("clicked")) - functools.reduce:
reduce(lambda a, b: a * b, nums)
AI/ML-এ lambda-র জায়গা:
- scikit-learn FunctionTransformer:
from sklearn.preprocessing import FunctionTransformer log_tf = FunctionTransformer(lambda X: np.log1p(X)) - PyTorch Lambda layer:
nn.Sequential( nn.Linear(10, 20), nn.ReLU(), nn.Lambda(lambda x: x * 2) # custom op ) - DataFrame transformations: column-wise quick op।
- Sorting model checkpoints:
sorted(paths, key=lambda p: int(p.stem.split('-')[-1]))।
Lambda-র alternatives:
- operator module:
from operator import attrgetter, itemgetter sorted(students, key=attrgetter("score")) # দ্রুত, পরিষ্কার sorted(items, key=itemgetter(1)) - functools.partial:
from functools import partial double = partial(multiply, 2) # multiply(2, x) - List comprehension:
[x ** 2 for x in nums] # map+lambda-এর চেয়ে Pythonic
সিদ্ধান্তের সূত্র:
- One-time, in-place, simple → lambda OK।
- Reusable, named, complex → def।
- Side-effect, multi-line → অবশ্যই def।
- Existing equivalent (operator, partial) → use that।
মূল উপলব্ধি: Lambda = scalpel, not hammer। নির্দিষ্ট কাজে চমৎকার, সাধারণ কাজে def। PyTorch/Pandas-এ দরকারি tool, কিন্তু overuse code-কে obscure করে। "Will I read this in 6 months?" — উত্তর "না" হলে — def।
প্র ০৪
Decorator কী? @something দেখলে কী ঘটে? AI/ML library-তে — @torch.no_grad(), @jit.script, @app.route — কেন এত প্রচলিত?
Decorator — Python-এর সবচেয়ে elegant feature-এর একটি। PEP 318 (২০০৩)-এ আসে। AI library design-এ কেন্দ্রীয়।
মূল ধারণা:
- Function-কে input হিসেবে নেয়, modified function ফেরত দেয়।
@decorator= syntactic sugar forfunc = decorator(func)।- "Behavior wrap"— original function-এ before/after logic।
মৌলিক উদাহরণ:
def timer(func):
def wrapper(*args, **kwargs):
import time
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.time()-start:.4f}s")
return result
return wrapper
@timer
def slow_op():
sum(i**2 for i in range(10**6))
slow_op() # auto-print timing
AI/ML-এ decorator-এর প্রভাব:
@torch.no_grad(): Inference-এ gradient disable। Memory ৫০% সাশ্রয়।@torch.no_grad() def predict(model, x): return model(x)@jit.script(TorchScript): Python function → optimized graph।@tf.function: TensorFlow eager → graph mode।@jax.jit: XLA compilation, ১০-১০০× speedup।@cache/@lru_cache: Memoization — repeated computation এড়াতে।@dataclass: Auto-generate __init__, __repr__।@property: Method → attribute-like access।@app.route("/predict"): Flask/FastAPI — endpoint registration।
Decorator with arguments:
def retry(times):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(times):
try:
return func(*args, **kwargs)
except Exception:
if i == times - 1: raise
return wrapper
return decorator
@retry(times=3)
def fetch_data():
...
Class decorator vs function decorator:
- Class — state রাখা যায়। যেমন: counter, cache।
- Function — stateless wrap।
functools.wraps— original metadata preserve।
Decorator stacking:
@cache
@validate_input
@log_calls
def expensive_op(x):
...
# expensive_op = cache(validate_input(log_calls(expensive_op)))
- নিচ থেকে উপরের দিকে apply — order matters।
সমস্যা ও সাবধানতা:
functools.wrapsছাড়া — original name, docstring lost।- Stack trace জটিল হয়।
- Type hint preservation কঠিন (Python 3.12-এ ParamSpec ভাল)।
- Debugger step-into through wrapper।
Built-in important decorators:
@staticmethod,@classmethod— class methods।@property— getter।@functools.cache(3.9+) — simple memoization।@functools.wraps— meta preserve।@contextlib.contextmanager— with-statement।
মূল উপলব্ধি: Decorator = behavior modification declarative। AI library-তে — boilerplate কমানোর primary tool। @torch.no_grad() না বুঝলে — PyTorch inference loop confusing। Decorator master হলে — Python-এর সৌন্দর্য full বুঝবেন।
অনুশীলন
-
Activation function: একটি function লিখুন
relu(x)যা negative-কে 0 ও positive-কে অপরিবর্তিত রাখে। List-এর প্রতিটি element-এ apply করুন।def relu(x): return max(0, x) nums = [-3, -1, 0, 2, 5] print([relu(n) for n in nums]) # অথবা print(list(map(relu, nums))) # [0, 0, 0, 2, 5] -
Multi-return: একটি function লিখুন
stats(nums)যা min, max ও average tuple-এ ফেরায়।def stats(nums): return min(nums), max(nums), sum(nums) / len(nums) mn, mx, avg = stats([10, 20, 30, 40, 50]) print(f"min={mn}, max={mx}, avg={avg}") # min=10, max=50, avg=30.0 -
Lambda sort: students =
[("রহিম", 85), ("ফাতেমা", 92), ("করিম", 78)]— score ascending ও descending — দু'ভাবে sort করুন lambda দিয়ে।students = [("রহিম", 85), ("ফাতেমা", 92), ("করিম", 78)] asc = sorted(students, key=lambda s: s[1]) desc = sorted(students, key=lambda s: s[1], reverse=True) print("Ascending:", asc) print("Descending:", desc)
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ০৬ · List comprehension ও iterator পরবর্তী পাঠ map/filter-এর Pythonic alternative — শক্তিশালী এক-লাইনের।
- পাঠ ০৪ · if/else ও loop আগের পাঠ
- পাঠ ০৮ · Error handling ও exception সম্পর্কিত Function-এ error সামাল দেওয়ার উপায়।
- সব AI Courses দেখুন ABCL TECH