python - 嵌套函数中的局部变量

标签 python scope closures nested-function

好吧,请耐心听我说,我知道这看起来会非常复杂,但请帮助我理解发生了什么。

from functools import partial

class Cage(object):
    def __init__(self, animal):
        self.animal = animal

def gotimes(do_the_petting):
    do_the_petting()

def get_petters():
    for animal in ['cow', 'dog', 'cat']:
        cage = Cage(animal)

        def pet_function():
            print "Mary pets the " + cage.animal + "."

        yield (animal, partial(gotimes, pet_function))

funs = list(get_petters())

for name, f in funs:
    print name + ":", 
    f()

给予:

cow: Mary pets the cat.
dog: Mary pets the cat.
cat: Mary pets the cat.

所以基本上,为什么我没有得到三种不同的动物? cage 不是“打包”到嵌套函数的本地作用域中吗?如果没有,对嵌套函数的调用如何查找局部变量?

我知道遇到此类问题通常意味着一个人“做错了”,但我想了解会发生什么。

最佳答案

嵌套函数在执行时而不是定义时从父作用域查找变量。

编译函数体,验证“自由”变量(未通过赋值在函数本身中定义),然后将其作为闭包单元绑定(bind)到函数,代码使用索引来引用每个单元。因此,pet_function一个 个自由变量 (cage),然后通过闭包单元(索引 0)引用该变量。闭包本身指向局部变量get_petters 函数中的 cage

当您实际调用该函数时,该闭包将用于查看您调用该函数时周围范围内的cage。问题就在这里。当您调用函数时,get_petters 函数已经完成了其结果的计算。在执行期间的某个时刻,cage 局部变量被分配给 'cow''dog''cat ' 字符串,但在函数末尾,cage 包含最后一个值'cat'。因此,当您调用每个动态返回的函数时,您将获得打印的值'cat'

解决方法是不依赖闭包。您可以使用部分函数来代替,创建新函数作用域,或者将变量绑定(bind)为关键字参数的默认值。 p>

  • 部分函数示例,使用 functools.partial() :

    from functools import partial
    
    def pet_function(cage=None):
        print "Mary pets the " + cage.animal + "."
    
    yield (animal, partial(gotimes, partial(pet_function, cage=cage)))
    
  • 创建新范围示例:

    def scoped_cage(cage=None):
        def pet_function():
            print "Mary pets the " + cage.animal + "."
        return pet_function
    
    yield (animal, partial(gotimes, scoped_cage(cage)))
    
  • 将变量绑定(bind)为关键字参数的默认值:

    def pet_function(cage=cage):
        print "Mary pets the " + cage.animal + "."
    
    yield (animal, partial(gotimes, pet_function))
    

无需在循环中定义 scoped_cage 函数,编译仅发生一次,而不是在循环的每次迭代中进行。

关于python - 嵌套函数中的局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58594515/

相关文章:

javascript - 单击 View 时 Appcelerator 范围问题

javascript - 无法弄清楚何时调用哪个函数

rust - 如何在检查相同值的循环中使用可变捕获变量的闭包?

javascript - 执行上下文何时创建?

javascript 闭包,谁能帮我理解为什么

python - 如何检查 django 员工用户首次登录管理面板?

python - 如何在游戏中添加积分系统和记分牌?

javascript - JavaScript 中 forEach 循环中的回调/函数作用域

python - 为什么这个正则表达式不返回任何内容?

原始输入多行字符串时python运行时错误