2012-06-22 41 views
6

Tôi đang bối rối về hành vi của phạm vi này:lạ chức năng Python phạm vi hành vi

class Bar: 
    def __init__(self): 
     for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]: 
      print "register", fn 
      def func_wrapper(filename): 
       print "called func wrapper", fn, filename 
      setattr(self, fn, func_wrapper) 

bar = Bar() 
bar.open("a") 
bar.remove("b") 
bar.listdir("c") 

này cho kết quả:

register open 
register openW 
register remove 
register mkdir 
register exists 
register isdir 
register listdir 
called func wrapper listdir a 
called func wrapper listdir b 
called func wrapper listdir c 

Nhưng tôi lại có thể ngờ rằng func_wrapper sẽ luôn là chức năng chính xác. Tôi biết rằng phạm vi của func_wrapper là toàn bộ chức năng nhưng tôi xác định lại nó trong mỗi vòng lặp lặp lại và trường hợp cuối cùng đã được lưu đi trong attrib. Tôi cũng đã cố gắng để thêm func_wrapper = None dưới đây setattr nhưng điều đó không giúp (cũng sẽ tự hỏi tôi ...).

Tôi có bị mù không? Tôi thậm chí không thực sự thấy cách làm việc xung quanh/sửa lỗi này.

+0

@heltonbiker: Bạn có thể xây dựng không? Làm thế nào tôi nên sử dụng một dict thay vì ở đây? Và tại sao? – Albert

+0

Tôi đã đọc kỹ hơn và đã xóa nhận xét trước đó. – heltonbiker

Trả lời

6

Hoặc với

class Bar: 
    def __init__(self): 
     for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]: 
      print "register", fn 
      def func_wrapper(filename, fn=fn): 
       print "called func wrapper", fn, filename 
      setattr(self, fn, func_wrapper) 

hay, mạnh mẽ hơn, với

def mkwrapper(fn): 
    def func_wrapper(filename): 
     print "called func wrapper", fn, filename 
    func_wrapper.__name__ = fn 
    return func_wrapper 

class Bar: 
    def __init__(self): 
     for fn in ["open","openW","remove","mkdir","exists","isdir","listdir"]: 
      print "register", fn 
      func_wrapper = mkwrapper(fn) 
      setattr(self, fn, func_wrapper) 

Trong ví dụ ban đầu của bạn, tất cả các chức năng được tạo ra truy cập vào cùng một biến ngoài fn, làm thay đổi trong mỗi chạy vòng lặp. Trong các ví dụ đã sửa, điều này được ngăn chặn.

+0

Ah yes, tôi nghĩ sth như thế này ... :) – Albert

+0

Tôi luôn nghĩ rằng có một cái gì đó * đặc biệt * về 'lambda' liên quan đến ràng buộc muộn, nhưng bây giờ tôi hiểu rằng chức năng thường xuyên thực sự có cùng một vấn đề, nó chỉ là chúng không thường được sử dụng giống như các hàm lambda. +1 cho câu hỏi và câu trả lời. –

+0

Tôi thực sự muốn mọi người sẽ ngừng đề xuất rằng thông số mặc định hack. –