Gần đây tôi bắt đầu chơi xung quanh với Python và tôi đã bắt gặp một thứ gì đó đặc biệt trong cách đóng cửa hoạt động. Hãy xem xét các mã sau đây:
adders=[0,1,2,3]
for i in [0,1,2,3]:
adders[i]=lambda a: i+a
print adders[1](3)
Nó xây dựng một mảng đơn giản các hàm lấy một đầu vào và trả về đầu vào đó được thêm bởi một số. Các hàm được xây dựng theo for
vòng lặp trong đó trình vòng lặp i
chạy từ 0
đến 3
. Đối với mỗi số này, một lambda
hàm được tạo để bắt i
và thêm nó vào đầu vào của hàm. Dòng cuối cùng gọi lambda
hàm thứ hai với 3
tham số. Tôi ngạc nhiên đầu ra là 6
.
Tôi mong đợi a 4
. Lý do của tôi là: trong Python mọi thứ đều là một đối tượng và do đó, mỗi biến là một con trỏ cần thiết cho nó. Khi tạo các bao lambda
đóng cho i
, tôi dự kiến nó sẽ lưu một con trỏ tới đối tượng số nguyên hiện được trỏ tới i
. Điều đó có nghĩa là khi i
được gán một đối tượng số nguyên mới, nó sẽ không ảnh hưởng đến các bao đóng được tạo trước đó. Đáng buồn thay, kiểm tra adders
mảng trong trình gỡ lỗi cho thấy rằng nó làm. Tất cả các lambda
hàm đề cập đến giá trị cuối cùng của i
, 3
kết quả là adders[1](3)
trả về 6
.
Điều này làm tôi tự hỏi về những điều sau đây:
- Những gì đóng cửa chụp chính xác?
- Cách thanh lịch nhất để thuyết phục các
lambda
chức năng để nắm bắt giá trị hiện tại củai
tại theo cách sẽ không bị ảnh hưởng khii
thay đổi giá trị của nó là gì?
i
để rời khỏi không gian tên?
print i
sẽ không hoạt động sau vòng lặp. Nhưng tôi đã thử nó cho chính mình và bây giờ tôi thấy ý của bạn - nó hoạt động. Tôi không có ý tưởng rằng các biến vòng lặp kéo dài sau thân vòng lặp trong python.
if
, with
, try
, vv