是在python中进行函数呼叫的作业



在构建参数化的装饰器时,我没有意识到在Python中不允许在嵌套功能中通过参数中通过的重新分配。进一步,我意识到这也是简单功能也是如此。我将演示置于以下嵌套函数:

def a(s):
    def b():
        def c():
#             nonlocal s                         # fix
            print(s)
#             while s:
#                 s -= 1                         # uncommenting raises UnboundLocalError 
            print(s)
            return None
        return c()
    return b()
a(3)
# 3
# 3

我希望通过添加注释的while循环来获得以下所需的输出:

a(3)
# 3
# 0

接下来,删除while循环的两行会产生以下错误,这表明将值重新分配到s会引起错误:

<ipython-input-37-7141eb599936> in c()
      3         def c():
      4 #             nonlocal s                 # fix
----> 5             print(s)
      6             while s:
      7                 s -= 1                   # uncommenting raises UnboundLocalError
UnboundLocalError: local variable 's' referenced before assignment

最后,Uncompomenting nonlocal解决了此问题,并按照本文建议提供所需的输出。

尽管解决了问题,但我想了解问题的根源。我注意到追溯指出了参数化参数s(例如print(s)(的首次使用,而不是指向实际导致错误的行(即while循环/分配(。

我怀疑在调用功能后,Python首先建立了本地范围的作业。然后,分配从外部范围内获得更高的优先级或覆盖的遗传变量。因此,如果没有对s分配,则使用了外部s。相比之下,通过分配,s在函数调用中重新定义,并且在初始分配之前的任何引用都会引起错误。这是正确的,还是有人可以解释Python实际在做什么?

如果一个函数包含对变量的分配(包括诸如 -=之类的增强作业,则变量自动局部,除非明确声明为 global(或 nonlocal(。它是自动全局的,而无需任何声明(因为当它没有值的源头时,它几乎不可能是本地变量(。此分析是在生成任何代码之前执行的,因此您会得到这样的情况,其中随后的代码行中的情况可能导致较早的行变成错误。

最新更新