了解 Python 闭包
Posted
技术标签:
【中文标题】了解 Python 闭包【英文标题】:Understanding Python Closures 【发布时间】:2015-07-29 15:55:30 【问题描述】:我一直认为 Python 2.7 的函数是指定义它们的作用域。考虑以下代码。为什么第二个输出不是“calculating: 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)
【问题讨论】:
【参考方案1】: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)
【讨论】:
【参考方案2】:从此代码(按您的预期工作)
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)
似乎不是函数定义的命名空间决定了闭包的性质,而是使用的变量的命名空间。 更多测试:
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)
所以正确的解释似乎是闭包保存了对其参数的引用而不是值。
【讨论】:
【参考方案3】:我认为您正在尝试使事情变得更难: 以下是使用闭包的方法:
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
【讨论】:
以上是关于了解 Python 闭包的主要内容,如果未能解决你的问题,请参考以下文章