https://docs.python.org/3/reference/executionmodel.html#resolution-of-names的最后一段说
在名称解析的上下文中,exec()和eval()的类定义块和参数是特殊的。类定义是可以使用和定义名称的可执行语句。这些引用遵循通常的名称解析规则,但在全局命名空间中查找未绑定的局部变量。
引用文字的最后一句是什么意思?起初,我从中推断出将打印以下代码1
a = 1
def foo():
a = 2
def bar():
class Bar:
b = a
print(Bar.b)
bar()
foo()
Run Code Online (Sandbox Code Playgroud)
但我错了-由上面的代码组成的模块,在运行时,会打印出2,即a类定义中的名称,即使它未绑定在类定义块中且未绑定在其外部的本地块中,也是如此。与文档所说的相反,它在全局名称空间中查找。
我尝试了下面描述的另一个代码段(使用一条del语句,该语句是将变量绑定到其中的构造)
a = 1
def foo():
a = 2
def bar():
class Bar:
del a
print(Bar.b)
bar()
foo()
Run Code Online (Sandbox Code Playgroud)
但是del声明提出了NameError: name 'a' is not defined。
所以,我不明白,那句话是什么意思?
根据文档,
如果名称绑定在块中,则该名称是该块的局部变量,除非声明为非局部或全局变量。
在您的第一个代码块中,a未绑定任何class Bar定义,因此它不是该块的局部变量。
绑定名称的一种方法是在赋值语句的左侧使用它。这是一个例子。
a = 1
def foo():
a = 2
class Bar:
b = a
a = 3
print(Bar.b)
foo()
Run Code Online (Sandbox Code Playgroud)
结果:
1
Run Code Online (Sandbox Code Playgroud)
这说明了“在全局名称空间中查找未绑定的局部变量”的原理- b = a使用的值a而不是ato 的局部值foo。
在您的第二个示例中,由于确定名称范围的目的是因为“在del语句中出现的目标也被视为绑定” ,因此a 被认为是class Bar块的局部。但是“在全局名称空间中查找未绑定的局部变量”并不相关,因为del不需要查找名称的值即可解除绑定。
为了达到良好的效果,我们可以通过实验确认一条del语句向解释器传达一个名称应被视为本地名称的信号。
a = 1
def foo():
a = 2
class Bar:
print(a)
del a
foo()
Run Code Online (Sandbox Code Playgroud)
结果:
1
Traceback (most recent call last):
File "C:\Users\Kevin\Desktop\test.py", line 7, in <module>
foo()
File "C:\Users\Kevin\Desktop\test.py", line 4, in foo
class Bar:
File "C:\Users\Kevin\Desktop\test.py", line 6, in Bar
del a
NameError: name 'a' is not defined
Run Code Online (Sandbox Code Playgroud)
在这里,我们看到print(a)成功查找了局部变量的值a,然后在下一行它崩溃了,因为del无法删除未绑定的局部变量。
| 归档时间: |
|
| 查看次数: |
68 次 |
| 最近记录: |