2012-01-20 26 views
18

Tôi chỉ chạy ngang qua số Closing over the loop variable considered harmful của Eric Lippert qua SO, và sau khi thử nghiệm, nhận ra rằng cùng một vấn đề tồn tại (và thậm chí còn khó khăn hơn để có được) trong Python.Có cách nào Pythonic để đóng trên một biến vòng lặp?

>>> l = [] 
>>> for r in range(10): 
... def foo(): 
...  return r 
... l.append(foo) 
... 
>>> for f in l: 
... f() 
... 
9 
9 
9 
# etc 

và, tiêu chuẩn C# workaround không làm việc (tôi giả sử vì bản chất của tài liệu tham khảo bằng Python)

>>> l = [] 
>>> for r in range(10): 
... r2 = r 
... def foo(): 
...  return r2 
... l.append(foo) 
... 
>>> for f in l: 
... f() 
... 
9 
9 
9 
# etc 

tôi nhận ra rằng đây là không nhiều của một vấn đề trong Python với nhấn mạnh chung của nó về cấu trúc đối tượng không đóng cửa, nhưng tôi tò mò nếu có một cách rõ ràng Pythonic để xử lý này, hoặc chúng ta phải đi đường JS của cuộc gọi chức năng lồng nhau để tạo ra các vars thực sự mới?

>>> l = [] 
>>> for r in range(10): 
...  l.append((lambda x: lambda: x)(r)) 
... 
>>> for f in l: 
...  f() 
... 
0 
1 
2 
# etc 

Trả lời

23

Một cách là sử dụng một tham số với giá trị mặc định:

l = [] 
for r in range(10): 
    def foo(r = r): 
     return r 
    l.append(foo) 

for f in l: 
    print(f()) 

mang

0 
1 
2 
3 
4 
5 
6 
7 
8 
9 

này hoạt động bởi vì nó định nghĩa một r trong phạm vi địa phương foo 's, và liên kết với các giá trị mặc định cho nó tại thời điểm foo được xác định.


Một cách khác là sử dụng một nhà máy chức năng:

l = [] 
for r in range(10): 
    def make_foo(r): 
     def foo(): 
      return r 
     return foo 
    l.append(make_foo(r)) 

for f in l: 
    print(f()) 

này hoạt động bởi vì nó xác định r trong phạm vi địa phương make_foo 's, và liên kết với một giá trị cho nó khi make_foo(r) được gọi. Sau đó, khi f() được gọi, r được tra cứu bằng cách sử dụng LEGB rule. Mặc dù r không được tìm thấy trong phạm vi địa phương của foo, nó được tìm thấy trong phạm vi kèm theo của make_foo.

+1

Ồ, tôi thích mẹo đối số mặc định đó. Nhà máy chức năng đó có ngữ nghĩa tương tự như điều lambda đôi ở cuối mỏ. Tuy nhiên, các nhà máy Lambda là nguyên nhân dễ đọc. – quodlibetor

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