Vì closure trong Python giữ tham chiếu tới biến, không giữ giá trị tại thời điểm tạo (late binding).
Cả ba lambda cùng trỏ tới một biến i; đến lúc gọi thì vòng lặp đã kết thúc và i đang là 2.
python
fns = [lambda: i for i in range(3)]
[f() for f in fns] # [2, 2, 2]Ba cách sửa:
python
# 1. default argument — được tính lúc định nghĩa hàm
fns = [lambda i=i: i for i in range(3)]
# 2. functools.partial — bind giá trị ngay lúc này
from functools import partial
fns = [partial(lambda i: i, i) for i in range(3)]
# 3. factory function — mỗi vòng lặp một scope mới
def make(i):
return lambda: i
fns = [make(i) for i in range(3)]Lỗi này ít khi hiện ra ở dạng lambda đứng riêng; nó thường hiện ra khi đăng ký callback/handler trong vòng lặp (button handler, task scheduler, retry hook) rồi tất cả cùng thao tác trên phần tử cuối.
Ngược lại, late binding cũng chính là thứ khiến closure "thấy" được giá trị mới nhất của biến ngoài — hữu ích với counter/accumulator dùng nonlocal.