在构建参数化装饰器时,我没有意识到 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
最后,取消注释 nonlocal
可以解决此问题,并按照 this post 的建议提供所需的输出。 。
虽然问题解决了,但我想了解问题的根源。我注意到回溯指向参数化参数 s
的第一次使用(例如 print(s)
),而不是指向实际导致错误的行(即while
循环/赋值)。
我怀疑在调用函数时,Python 首先建立局部作用域的分配。然后,赋值的优先级高于或覆盖从外部作用域继承的变量。因此,如果没有分配s
,则使用外部s
。相比之下,对于赋值,s
在函数调用时重新定义,并且初始赋值之前的任何引用都会引发错误。这是正确的吗?或者有人可以解释一下Python实际上在做什么吗?
最佳答案
如果函数包含对变量的赋值(包括扩展赋值,例如 -=
,则该变量自动为本地变量,除非显式声明为 global
(或 >nonlocal
)。如果没有赋值,它会自动成为全局变量,无需任何声明(因为当没有值源时,它几乎不可能是局部变量)。此分析在任何代码执行之前执行。生成的,因此您会遇到这样的情况,后续的代码行可能会导致前面的代码行成为错误。
关于python - Python 中的函数调用时会进行赋值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43600957/