在Python中,内部定义的函数传递给其他函数时,如何保留变量?
比如说,为什么这个能正常工作呢?
def func1(func1var):
def innerfunc(innerfuncvar):
if func1var == 1:
print innerfuncvar
else:
print 5
func2(innerfunc)
def func2(function):
function(9)
当在func2
里面调用innerfunc
的时候,它是怎么知道func1var
的值的呢?
3 个回答
每次你调用 func1(func1var)
的时候,Python 实际上会创建一个 新的 函数 innerfunc()
。因为在创建 innerfunc()
的时候,func1var
的值是完全确定的,所以新创建的 innerfunc()
函数里面的代码会包含正确的 func1var
的值。
你创建了一个闭包。简单来说,从内部函数的角度来看,可以这样理解:
func1var = whatever
def func2(function):
function(9)
def innerfunc(innerfuncvar):
if func1var = 1:
print innerfuncvar
else:
print 5
func2(innerfunc)
内部函数并不关心func1var
是在外部作用域还是全局作用域,它只是在每个外层作用域中查找,从自己的局部作用域开始。这就像你在一个模块的类或函数内部引用模块的全局变量一样。
Python 其实为你做了很多事情。当你在一个函数里面定义另一个函数时,你可以在里面使用外面函数的变量。这种情况在任何层级的嵌套中都是成立的(也就是说,你可以在一个函数里面再放一个函数,里面再放一个函数,依此类推……最里面的函数可以使用任何外层函数的变量)。如果有名字冲突,最里面的那个变量会被优先使用。
更有意思的是,Python 会把你在外层函数中使用的变量捕获并存储在内层函数中,这个特性叫做 闭包。所以你不仅可以把一个函数传给另一个函数,就像你现在做的那样,还可以从一个函数中 返回 一个函数。即使外层函数已经不在运行,内层函数仍然可以访问在定义时有效的外层函数的变量。这是一个比较高级的特性,但它让你可以做到这样的事情:
def make_adder(increment):
def adder(number):
return number + increment
adder.__name__ = "adder(%s)" % increment
return adder
这个函数是一个 创建 函数的函数,它会把指定的值加到里面。例如:
add1 = make_adder(1)
add5 = make_adder(5)
print add1(10) # 11
print add5(10) # 15
在这个例子中,你传给 make_adder
的值会被捕获并存储在返回的函数中。这让你可以创建一堆函数,它们可以把任何数字加到它们的参数上。虽然这个例子看起来很简单,在现实生活中并不是特别有用,但它很好地说明了这个特性。