【发布时间】:2020-11-21 14:46:49
【问题描述】:
我只是在检查我关于 Python 范围界定的心智模型并感到困惑。前两个示例匹配我的模型,第三个示例不匹配。
我假设 Python 有 4 个作用域:
- 本地
- 封闭
- 全球
- 内置
我想这 4 个作用域就像字典一样。内置的一个是预定义的,其他的是在一些操作后生成的:
- 全局:主脚本文件创建一个变量。脚本完成执行后,此作用域将被终止。
- 本地:在函数内调用变量。一旦函数执行完毕,这个作用域就会被杀死
- 封闭:函数
B在函数A中定义。一旦调用了B,A的本地范围就变成了B的封闭范围。一旦B完成执行,此作用域就会被终止。
我假设 Python 在内存中有这 4 个字典,并且基本上每次都尝试所有 4 个:
- 变量是否存在于本地范围内?用它。如果没有,请转到 2
- 变量是否存在于封闭范围内?用它。如果没有,请转到 3。
- 变量是否存在于全局范围内?用它。如果没有,请转到 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
【问题讨论】:
-
我还注意到
def x(): y给出了NameError,但def x(): y; y = 1给出了UnboundLocalError。错误后的含义代码会影响错误。我不确定这是我的心智模型的另一个问题还是同样的问题。 -
在运行时唯一可能发生的后备是全局 -> 内置。将变量分类为局部变量、非局部变量(您所谓的“封闭”)或全局变量完全是在编译时进行的;基本上,如果该函数中没有明确的
global或nonlocal声明,您分配给(函数中的任何位置)的任何变量都会变为局部变量。 -
@jasonharper 如果您将该评论作为答案,我会接受。如果您添加有关 Python 如何执行内容的更多详细信息(编译时会发生什么,运行时会发生什么),我会 +1(或 +50)是 :-)