考虑这两个Python文件:
# file1.py
global_var = "abc"
class A:
x = 1
glb = global_var
y = x + 1
class B:
z = 3
glb = global_var
zz = B.z
print(f"{A.B.z=}")
print(f"{A.zz=}")
# file2.py
global_var = "abc"
class A:
x = 1
glb = global_var
y = x + 1
class B:
z = y + 1
glb = global_var
zz = B.z
print(f"{A.B.z=}")
print(f"{A.zz=}")
人们会期望他们做完全相同的事情。但他们没有!
$ python file1.py
A.B.z=3
A.zz=3
$ python file2.py
Traceback (most recent call last):
File "file2.py", line 4, in <module>
class A:
File "file2.py", line 8, in A
class B:
File "file2.py", line 9, in B
z = y + 1
NameError: name 'y' is not defined
B
的定义可以访问全局范围,而不能访问A
的范围?y=x1
应该工作,而z=y1
不应该工作?这是一个设计决策,还是CPython未定义的行为?Chepner已经回答了这个问题,但简而言之:局部变量在全局命名空间中查找,因此类嵌套在代码示例中的方式符合预期。
如上文所述,其工作正常。
它们不适用于具有LEGB规则/realpython的嵌套函数:
定义类时,您正在创建一个新的本地Python作用域。在类的顶层指定的名称在此本地作用域中。在class语句中指定的名称与其他地方的名称不冲突。您可以说这些名称遵循LEGB规则,其中class块表示L层
在另一个类中嵌套一个类也不是很常见,通常你是这样做的类继承:
class B(A):
y = A.y
z = y + 1
glb = global_var
从…起https://docs.python.org/3/reference/executionmodel.html:
类定义块和exec()和ava()的参数在名称解析的上下文中是特殊的。类定义是可以使用和定义名称的可执行语句。这些引用遵循名称解析的正常规则,但在全局命名空间中查找未绑定的局部变量除外。类定义的命名空间成为类的属性字典。类块中定义的名称范围仅限于类块;它不扩展到方法的代码块——这包括理解和生成器表达式,因为它们是使用函数范围实现的。这意味着以下操作将失败:
在B
的定义中,y
是一个未绑定的局部变量,因此在全局范围(未定义)中查找,而不是在包含的类
语句创建的命名空间中查找。
class
语句根本没有定义作用域;它创建了一个命名空间,该命名空间被传递给元类,以便构造一个新类。
问题内容: 注意:这是在PHP中处理变量范围的参考问题。请关闭所有适合此模式的问题,以作为该问题的重复。 PHP中的“可变范围”是什么?一个.php文件中的变量可以在另一个文件中访问吗?为什么有时会出现 “未定义变量” 错误? 问题答案: 什么是“可变范围”? 变量具有有限的“作用域”或“可从其访问的位置”。仅仅因为你写一次 的地方 在你的应用程序并不意味着你可以参照从 到处 其他的应用程序中。该
本文向大家介绍Python 如何访问外围作用域中的变量,包括了Python 如何访问外围作用域中的变量的使用技巧和注意事项,需要的朋友参考一下 在表达式中引用变量时,Python 会按照如下的顺序遍历各个作用域,寻找该变量: 当前函数作用域 任何外围作用域(比如包含当前函数的其他函数) global 作用域,即代码所在的模块的作用域 如果上述作用域内都找不到变量,就会报 NameError 异常。
本文向大家介绍js的哪些操作可以改变作用域链?相关面试题,主要包含被问及js的哪些操作可以改变作用域链?时的应答技巧和注意事项,需要的朋友参考一下 比较有名的是的间接调用:
问题内容: 如何从类定义中的列表理解中访问其他类变量?以下内容在Python 2中有效,但在Python 3中失败: Python 3.2给出了错误: 尝试Foo.x也不起作用。关于如何在Python 3中执行此操作的任何想法? 一个稍微复杂的激励示例: 在此示例中,apply()这是一个不错的解决方法,但可悲的是它已从Python 3中删除。 问题答案: 类范围和列表,集合或字典的理解以及生成器
问题内容: 我注意到当在try {}中使用以下变量时,例如,从最后我不能在它们上使用方法: 但是,如果将声明放置在Try {}之前的main()中,则程序编译时没有错误,那么有人可以指出解决方案/答案/解决方法吗? 问题答案: 在进入块之前,需要声明变量,以使它们在方法的其余部分范围内:
【闭包】和【作用域链】到底是谁让函数中的变量可以访问外层作用域中的变量?