在Python中,内部定义的函数传递给其他函数时,如何保留变量?

9 投票
3 回答
667 浏览
提问于 2025-04-16 23:41

比如说,为什么这个能正常工作呢?

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 个回答

2

每次你调用 func1(func1var) 的时候,Python 实际上会创建一个 新的 函数 innerfunc()。因为在创建 innerfunc() 的时候,func1var 的值是完全确定的,所以新创建的 innerfunc() 函数里面的代码会包含正确的 func1var 的值。

7

你创建了一个闭包。简单来说,从内部函数的角度来看,可以这样理解:

func1var = whatever

def func2(function):
    function(9)

def innerfunc(innerfuncvar):
    if func1var = 1:
         print innerfuncvar
    else:
         print 5

func2(innerfunc)

内部函数并不关心func1var是在外部作用域还是全局作用域,它只是在每个外层作用域中查找,从自己的局部作用域开始。这就像你在一个模块的类或函数内部引用模块的全局变量一样。

6

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 的值会被捕获并存储在返回的函数中。这让你可以创建一堆函数,它们可以把任何数字加到它们的参数上。虽然这个例子看起来很简单,在现实生活中并不是特别有用,但它很好地说明了这个特性。

撰写回答