🌱 [Python] 13 - Inner Function — Hàm lồng nhau & Closure
Trong Python, bạn có thể định nghĩa một hàm bên trong một hàm khác, gọi là inner function (hàm lồng nhau). Hàm lồng nhau (nested function) và khái niệm closure là một trong những công cụ mạnh mẽ để giữ trạng thái, tạo hàm động, và thực hiện các mô hình lập trình cao hơn như decorator.
1 – Nested / Inner Functions
Hàm lồng nhau (inner function) là hàm được định nghĩa bên trong một hàm khác. Hàm bên trong có thể truy cập biến của hàm ngoài (enclosing function).
Ví dụ:
def outer():
message = "Hello from outer"
def inner():
print(message)
inner()
outer() # Output: Hello from outer
Ở ví dụ này, inner() là hàm lồng nhau và tham chiếu đến biến `message` được định nghĩa trong hàm outer(). Khi outer() được gọi, inner() được thực thi và hiển thị giá trị `message`.
Tại sao cần sử dụng inner functions?
Các lý do và lợi ích khi sử dụng inner functions:
- Ẩn chi tiết thực thi: bạn có thể giữ hàm phụ trợ bên trong và chỉ lộ API chính.
- Giúp tổ chức code gọn hơn, đóng gói logic phụ vào trong hàm lớn hơn.
- Tạo closure (giữ trạng thái) — inner function có thể nhớ biến của hàm bên ngoài sau khi hàm ngoài đã kết thúc.
- Hỗ trợ viết decorator, factory functions, hoặc các cấu trúc hàm động.
2 – Closures
Closure là khi inner function “nhớ” môi trường nơi nó được tạo ra — tức là nó giữ các biến từ hàm ngoài kể cả khi hàm ngoài đã kết thúc. Closure cho phép dữ liệu bị “đóng gói” và duy trì trạng thái giữa các lần gọi hàm inner.
Ví dụ closure:
- def make_multiplier(n):
- def multiplier(x):
- return x * n
- return multiplier
- times5 = make_multiplier(5)
- print(times5(10)) # 50
- print(times5(7)) # 35
Ở ví dụ trên, `multiplier` là inner function và `make_multiplier` trả về function này. Khi `make_multiplier(5)` được gọi, nó tạo closure giữ giá trị `n = 5`, và `multiplier` dùng giá trị đó khi sau này được gọi.
3 – Capturing variables (free variables)
Trong closure, “free variables” là các biến không được định nghĩa trong inner function nhưng được sử dụng trong đó — thường là biến của hàm ngoại. Python cho phép inner function truy cập các biến này (miễn là bạn không gán lại chúng trực tiếp).
Ví dụ:
def outer():
count = 0
def inner():
# count = count + 1
Nếu bạn muốn "gán lại" biến `count` từ trong `inner()`, bạn cần dùng từ khóa `nonlocal`:
- def outer():
- count = 0
- def inner():
- nonlocal count
- count += 1
- print("Count is", count)
- return inner
- f = outer()
- f() # Count is 1
- f() # Count is 2
4 – Use cases & ví dụ thực tế
Một số ứng dụng thường gặp của inner functions và closures:
- Factory functions: tạo hàm tùy biến (như `make_multiplier`).
- Decorator: inner function giữ logic bổ sung quanh hàm gốc.
- Caching / memoization: lưu kết quả tính trước đó để tăng tốc.
- Hàm callback giữ trạng thái: trong GUI, thread, hoặc công cụ bất đồng bộ.
Ví dụ decorator dùng inner function
- def decorator(func):
- def wrapper(*args, **kwargs):
- print("Before call")
- result = func(*args, **kwargs)
- print("After call")
- return result
- return wrapper
- @decorator
- def greet(name):
- print("Hello, " + name + "!")
- greet("Alice")
- # Before call
- # Hello, Alice!
- # After call
Ví dụ closure trong caching
- def cached_multiplier(n):
- cache = {}
- def multiply(x):
- if x in cache:
- return cache[x]
- result = x * n
- cache[x] = result
- return result
- return multiply
- times4 = cached_multiplier(4)
- print(times4(5)) # 20, tính mới
- print(times4(5)) # 20, trả từ cache
5 – Lưu ý, hạn chế & best practices
Dưới đây là những điều bạn nên nhớ khi dùng inner functions / closures:
- Chỉ sử dụng closure khi cần giữ trạng thái giữa các lần gọi hàm.
- Tránh biến free variables trở nên phức tạp hoặc dễ gây lỗi khi gán lại — phải dùng `nonlocal`.
- Đừng abuse hàm lồng nhau nếu logic đơn giản — có thể tạo ra code khó đọc.
- Trong decorator, giữ phần logic gọn, rõ ràng và thêm docstring cho hàm wrapper nếu có thể.
- Hiểu rõ scope của biến: local, nonlocal và global để tránh lỗi unbound / name errors.
Inner function và closure là khái niệm mạnh mẽ trong Python, giúp bạn viết hàm linh hoạt, giữ trạng thái mà không dùng biến toàn cục. Chúng được sử dụng rộng rãi trong decorator, factory, caching, và callback. Tuy nhiên cần dùng cẩn trọng để tránh code khó hiểu và lỗi phạm vi biến. Khi làm chủ được inner functions và closure, bạn sẽ mở ra rất nhiều khả năng trong việc thiết kế code Python chuyên nghiệp hơn.
>>>>>> Follow ngay <<<<<<<
Để nhận được những bài học miễn phí mới nhất nhé 😊
Chúc các bạn học tập tốt 😊