为什么 Python 不从封闭变量范围切换到局部变量范围?

Why isn't Python switching from enclosing to local variable scope?

我只是在检查 Python 中关于范围界定的心智模型,然后感到困惑。前两个示例与我的模型匹配,第三个示例不匹配。

我假设 Python 有 4 个作用域:

我想这 4 个范围就像字典一样。内置的是预定义的,其他的是在一些操作后生成的:

我假设 Python 内存中有这 4 个词典,基本上每次都尝试全部 4 个:

  1. 变量是否存在于本地范围内?用它。如果不是,则转到 2
  2. 变量是否存在于封闭范围内?用它。否,转3。
  3. 变量是否存在于全局范围内?用它。否,转4。
  4. 变量是否存在于内置函数中?用它。如果不是,则抛出 NameError

我特别假设变量可以从正在使用的封闭范围切换到正在使用的局部范围。显然不是这样。有人可以解释为什么吗?我的心理模型与实际发生的情况是否可能存在更大差异?

示例 1

这会打印“本地”

def foo():
    min = lambda n: "enclosing"

    def bar():
        """Bar is enclosed by 'foo'"""
        min = lambda n: "local"
        print(min([1, 2, 3]))

    bar()


foo()

示例 2

这会打印“封闭”

def foo():
    min = lambda n: "enclosing"

    def bar():
        """Bar is enclosed by 'foo'"""
        print(min([1,2,3]))

    bar()


foo()

示例 3

def foo():
    min = lambda n: "enclosing"

    def bar():
        """Bar is enclosed by 'foo'"""
        print(min([1,2,3]))
        min = lambda n: "local"
        print(min([1, 2, 3]))

    bar()


foo()

给予

Traceback (most recent call last):
  File "example.py", line 13, in <module>
    foo()
  File "example.py", line 10, in foo
    bar()
  File "example.py", line 6, in bar
    print(min([1,2,3]))
UnboundLocalError: local variable 'min' referenced before assignment

规则是,如果您在函数体内的任何位置赋值给变量,则该变量在整个函数中都被视为局部变量。

如果你想引用一个全局变量,你必须通过声明明确说明

global my_variable

如果你想在定义它的最近封闭范围内引用变量,你必须将它声明为

nonlocal my_variable

因此,这里没有发生任何特殊情况:确定变量是局部变量的一般规则仍然适用。