2015-05-18 20 views
6

Tôi luôn nghĩ rằng các hàm Python 2.7 tham chiếu đến phạm vi mà chúng đã được định nghĩa. Hãy xem xét mã sau đây. Tại sao đầu ra thứ hai không phải là "tính: sin"?Hiểu về các đóng cửa của Python

Có cách nào để sửa đổi mã để mã hoạt động như mong đợi không?

import math 

mymath = dict() 

for fun in ["sin", "cos"]: 
    def _impl(val): 
     print "calculating: %s" % fun 
     return getattr(math, fun)(val) 
    mymath[fun] = _impl 

# calculating: cos 
print mymath["cos"](math.pi) 

# calculating: cos <- why? 
print mymath["sin"](math.pi) 

Trả lời

7

Giá trị của fun được đánh giá khi hàm được gọi.

Trong ví dụ bạn đã cung cấp, fun là biến toàn cục và giá trị của nó là "cos" sau khi vòng lặp for chạy.

Tôi nghĩ bạn mong đợi giá trị fun được thay thế khi bạn tạo hàm, nhưng không phải. Hàm này đánh giá giá trị của biến khi nó chạy giống như nó được cho là.

Nó không phải về không gian tên mà bạn xác định hàm, nhưng không gian tên mà bạn chạy hàm.

import math 

mymath = dict() 

for fun in ["sin", "cos"]: 
    def _impl(val): 
     print "calculating: %s" % fun 
     return getattr(math, fun)(val) 
    mymath[fun] = _impl 


fun = 'tan' 
# will print and calculate tan 
print mymath["cos"](math.pi) 
2

Từ mã này (mà làm việc như bạn dự định)

my = {} 

def makefun(fun): 
    def _impl(x): 
    print fun, x 
    return _impl 

for fun in ["cos", "sin"]: 
    my[fun] = makefun(fun) 

# will print 'cos' 
my['cos'](1) 
fun = 'tan' 
# will print 'cos' 
my['cos'](2) 

có vẻ như nó không phải là không gian tên của định nghĩa chức năng mà quyết định về bản chất của việc đóng cửa nhưng thay vào đó là không gian tên của biến được sử dụng. Nhiều thử nghiệm:

my = dict() 

fun = '' 

def makefun(): 
    global fun #This line is switched on or off 
    fun = 'sin' 
    def _impl(x): 
    print fun, x 
    return _impl 

test = makefun() 

#gives sin 1 
test(1) 
fun = 'cos' 
#gives sin 2 if line global fun is used 
#gives cos 2 if line global fun is NOT used 
test(2) 

Vì vậy, lời giải thích đúng dường như là việc đóng cửa giúp tiết kiệm một tham chiếu đến đối số của nó và không phải là một giá trị.

0

Tôi nghĩ rằng bạn đang cố gắng để làm những điều khó khăn hơn: Đây là cách bạn có thể làm điều đó với đóng cửa:

import math 

mymath = dict() 


def funcmaker(fun): 
    print "creating %s function" % fun 
    def calculate(val): 
     print "calculating: %s" % fun 
     return getattr(math, fun)(val) 
    return calculate 

print funcmaker("sin")(math.pi) 
print funcmaker("cos")(math.pi) 

Trên đang mang đến cho bạn những kết quả sau:

creating sin function 
calculating: sin 
1.22464679915e-16 
creating cos function 
calculating: cos 
-1.0 
Các vấn đề liên quan