2010-08-07 60 views
39

Tôi đang cố tạo các chức năng bên trong vòng lặp và lưu chúng trong từ điển. Vấn đề là tất cả các mục trong từ điển dường như kết thúc ánh xạ tới hàm được tạo cuối cùng. Mã này đi như thế này:Tạo các chức năng trong vòng lặp

d = {} 
def test(**kwargs): 
    for k in kwargs: 
     def f(): 
      print k, kwargs[k] 
     d[k] = f 
     f() 

test(foo=1, bar=2) 
print 'should print the same output as before' 
d['foo']() 
d['bar']() 

này kết quả đầu ra:

foo 1 
bar 2 
should print the same output as before 
bar 2 
bar 2 

Bất cứ ý tưởng tại sao?

+1

như một lời nhắc nhở cho bản thân mình: http://docs.python-guide.org/en/latest/writing/gotchas/#late-binding-closures –

Trả lời

82

Bạn đang chạy vào một vấn đề với cuối ràng buộc - mỗi chức năng nhìn lên k muộn càng tốt (do đó, khi gọi bên ngoài test, điều này xảy ra sau khi kết thúc vòng lặp).

Dễ dàng cố định bằng cách buộc đầu ràng buộc: thay đổi def f(): để def f(k=k): - giá trị mặc định (bên phải k trong k=k là một giá trị mặc định cho tên đối số k, đó là trái k trong k=k) đều ngước nhìn def thời gian, không phải tại call thời gian, vì vậy về cơ bản họ là một cách để cụ thể tìm kiếm ràng buộc sớm.

Nếu bạn đang lo lắng về f nhận được một cuộc tranh cãi thêm (và do đó có khả năng được gọi là sai lầm), có một cách tinh vi hơn có liên quan đến sử dụng một đóng cửa như một "nhà máy chức năng":

def make_f(kwargs, k): 
    def f(): 
     print k, kwargs[k] 
    return f 

và trong vòng lặp của bạn sử dụng f = make_f(kwargs, k) thay vì câu hỏi def.

Các vấn đề liên quan