理解Python闭包

理解Python闭包,python,python-2.7,scope,closures,Python,Python 2.7,Scope,Closures,我一直认为Python2.7函数指的是它们在中定义的范围。考虑下面的代码。为什么第二个输出不是“计算:sin” 有没有办法修改代码,使其按预期工作 import math mymath = dict() for fun in ["sin", "cos"]: def _impl(val): print "calculating: %s" % fun return getattr(math, fun)(val) mymath[fun] = _imp

我一直认为Python2.7函数指的是它们在中定义的范围。考虑下面的代码。为什么第二个输出不是“计算:sin”

有没有办法修改代码,使其按预期工作

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)
导入数学
mymath=dict()
为了在[“罪”,“因”]中获得乐趣:
def_impl(val):
打印“正在计算:%s”%s
返回getattr(数学、娱乐)(val)
我的数学[乐趣]=\u impl
#计算:cos
打印mymath[“cos”](math.pi)

#计算:cos调用函数时计算
fun
的值

在您提供的示例中,
fun
是一个全局变量,它的值在
for
循环运行后为“cos”

我认为您希望在创建函数时替换
fun
的值,但事实并非如此。函数在按预期方式运行时计算变量的值

它不是关于定义函数的名称空间,而是关于运行函数的名称空间

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)
根据此代码(按照您的预期工作)

似乎不是函数定义的名称空间决定闭包的性质,而是所用变量的名称空间。 更多测试:

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)

因此,正确的解释似乎是闭包保存了对其参数的引用,而不是一个值。

我认为您试图让事情变得更难: 以下是使用闭包的方法:

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)
上面的代码给出了以下结果:

creating sin function
calculating: sin
1.22464679915e-16
creating cos function
calculating: cos
-1.0
creating sin function
calculating: sin
1.22464679915e-16
creating cos function
calculating: cos
-1.0