python - Python 中的函数调用时会进行赋值吗?

标签 python function variable-assignment

在构建参数化装饰器时,我没有意识到 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/

相关文章:

PHP 简短语句使变量回退到默认值

scala - x = y = 1 在 Scala 中?

python - 检查对象是否为异常类

python - 如何将多维数据传入xgboost模型

python - 将python字符串转换为字典

javascript - javascript如何获取函数的返回值

javascript - 将变量传递给对象方法javascript

python - 将数据框从多列 reshape 为一列

python - 为什么可变变量不能在没有链接的情况下一起分配?

编译器可以优化嵌套循环吗?