
Các mẫu thiết kế lập trình function trong Python
Lập trình hàm (functional programming) trong Python không chỉ là dùng map, filter, reduce. Các mẫu thiết kế (design patterns) hàm giúp code ngắn gọn, dễ test, ít bug và tận dụng đa nhân. Bài viết này giới thiệu 7 pattern phổ biến nhất.

1. Pure Functions (Hàm thuần túy)
Hàm thuần túy: cùng input luôn cho cùng output, không side effect (không sửa global state, không I/O, không mutate argument).
# Pure
def add(a, b):
return a + b
# Impure - mutates argument
def append_item(lst, item):
lst.append(item) # side effect!
return lst
# Pure version
def append_item_pure(lst, item):
return lst + [item]
Lợi ích: Dễ test (không cần mock), dễ cache (memoization), an toàn cho đa luồng, dễ reasoning.
2. Higher-Order Functions (Hàm bậc cao)
Hàm nhận hàm khác làm tham số hoặc trả về hàm. Python hỗ trợ first-class functions.
def apply_twice(func, x):
return func(func(x))
def add_one(x):
return x + 1
result = apply_twice(add_one, 5) # 7
# Built-in higher-order functions
numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
evens = list(filter(lambda x: x % 2 == 0, numbers))
3. Function Composition (Hợp thành hàm)
Kết nối output của hàm này làm input của hàm kia. Pipeline dữ liệu một chiều.
from functools import reduce
def compose(*funcs):
return lambda x: reduce(lambda acc, f: f(acc), funcs, x)
# Usage
process = compose(str.strip, str.lower, lambda s: s.replace(' ', '_'))
clean = process(" Hello World ") # "hello_world"
# Or using pipe operator (Python 3.11+)
def pipe(x, *funcs):
for f in funcs:
x = f(x)
return x
result = pipe(" Hello ", str.strip, str.upper, len) # 5

4. Currying & Partial Application
Currying: biến hàm nhiều tham số thành chuỗi hàm một tham số. Partial application: fix một số tham số trước.
from functools import partial
# Currying manual
def multiply_curried(a):
def inner(b):
return a * b
return inner
times_3 = multiply_curried(3)
times_3(4) # 12
# Partial application (thực tế hơn)
def power(base, exponent):
return base ** 2
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
square(5) # 25
cube(3) # 27
# Real-world: config functions
def connect_db(host, port, db_name, user, password):
pass
connect_local = partial(connect_db, host='localhost', port=5432)
connect_prod = partial(connect_db, host='prod.db.com', port=5432)
5. Decorators as Higher-Order Functions
Decorator bản chất là higher-order function: nhận function, trả về function mới mở rộng hành vi.
import time
from functools import wraps
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} took {end - start:.4f}s")
return result
return wrapper
@timer
def slow_function():
time.sleep(0.1)
# Class-based decorator with state
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"Call #{self.count}")
return self.func(*args, **kwargs)
@CountCalls
def greet(name):
return f"Hello {name}"
6. Memoization & Caching
Cache kết quả hàm tốn kém với cùng input. functools.lru_cache là built-in.
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
fibonacci(50) # Tính ngay lập tức nhờ cache
# Custom cache với TTL
import time
def ttl_cache(ttl_seconds):
cache = {}
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
key = (args, tuple(sorted(kwargs.items())))
now = time.time()
if key in cache and now - cache[key][1] < ttl_seconds:
return cache[key][0]
result = func(*args, **kwargs)
cache[key] = (result, now)
return result
return wrapper
return decorator
7. Strategy Pattern with Functions
Thay vì class hierarchy, dùng dict map string -> function. Python làm pattern này tự nhiên.
# Thay vì class PaymentStrategy...
def pay_credit_card(amount): return f"Charged ${amount} to credit card"
def pay_paypal(amount): return f"Paid ${amount} via PayPal"
def pay_crypto(amount): return f"Sent ${amount} in BTC"
STRATEGIES = {
'credit': pay_credit_card,
'paypal': pay_paypal,
'crypto': pay_crypto,
}
def process_payment(method, amount):
strategy = STRATEGIES.get(method)
if not strategy:
raise ValueError(f"Unknown method: {method}")
return strategy(amount)
# Dễ mở rộng: chỉ thêm entry vào dict
STRATEGIES['apple_pay'] = lambda a: f"Apple Pay: ${a}"
Kết luận
Python không ép buộc lập trình hướng đối tượng. Các pattern hàm: pure functions, higher-order functions, composition, currying/partial, decorators, memoization, function strategy giúp code ngắn, rõ ràng, dễ bảo trì. Kết hợp với type hints (Callable, Protocol) cho an toàn tĩnh.
Nguồn: Python functools docs, Real Python Functional Programming, Python Patterns repo
