为什么一个 class-inside-a-class 不在另一个 class-inside-a-class 的范围内?
Why is one class-inside-a-class not in the scope of another class-inside-a-class?
考虑以下代码:
from enum import Enum
class A(object):
class B(object):
blah = "foo"
derp = "bar"
class SubA(object):
def __init__(self):
self.value = B.derp
这引发了 NameError
>>> A.SubA()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 10, in __init__
self.value = B.derp
NameError: name 'B' is not defined
另一方面,将 B.derp
替换为 A.B.derp
可使代码按预期工作。
为什么 Python 的范围界定会以这种方式解决这个问题,为什么 应该 这在 Python 的设计中有意义?
如 PEP 227 中所述,class 主体的作用域在嵌套在其中的其他作用域内不可用。因此,在您的示例中获得 B
的 NameError 的原因与在这种情况下获得 NameError 的原因相同:
class Foo(object):
x = 88
def foo(self):
print(x)
class 主体中定义的函数(即方法)无法访问 class 主体范围;嵌套的 classes(或嵌套在其中的函数)也不行。
A.B.derp
有效是因为 A
在 global 范围内,它总是可以访问的。
但是,请注意,如果您尝试直接在 class 正文中使用它,即使 A.B.derp
也不起作用:
class A(object):
class B(object):
derp = 88
class SubA(object):
stuff = A.B.derp
这不行,因为引用A.B.derp
的行是在创建A
的过程中执行的,所以A
还不存在,无法引用.
虽然 类 定义了一个新的命名空间,但它们不会为方法体内使用的名称创建范围。在引用它们时,名称必须是完全限定的。 self.something
或 cls.something
的用途。
尝试使用像 A.B.something
这样的完全限定名称。 A
与 B
在同一个命名空间,但不在同一个变量范围内。
考虑以下代码:
from enum import Enum
class A(object):
class B(object):
blah = "foo"
derp = "bar"
class SubA(object):
def __init__(self):
self.value = B.derp
这引发了 NameError
>>> A.SubA()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 10, in __init__
self.value = B.derp
NameError: name 'B' is not defined
另一方面,将 B.derp
替换为 A.B.derp
可使代码按预期工作。
为什么 Python 的范围界定会以这种方式解决这个问题,为什么 应该 这在 Python 的设计中有意义?
如 PEP 227 中所述,class 主体的作用域在嵌套在其中的其他作用域内不可用。因此,在您的示例中获得 B
的 NameError 的原因与在这种情况下获得 NameError 的原因相同:
class Foo(object):
x = 88
def foo(self):
print(x)
class 主体中定义的函数(即方法)无法访问 class 主体范围;嵌套的 classes(或嵌套在其中的函数)也不行。
A.B.derp
有效是因为 A
在 global 范围内,它总是可以访问的。
但是,请注意,如果您尝试直接在 class 正文中使用它,即使 A.B.derp
也不起作用:
class A(object):
class B(object):
derp = 88
class SubA(object):
stuff = A.B.derp
这不行,因为引用A.B.derp
的行是在创建A
的过程中执行的,所以A
还不存在,无法引用.
虽然 类 定义了一个新的命名空间,但它们不会为方法体内使用的名称创建范围。在引用它们时,名称必须是完全限定的。 self.something
或 cls.something
的用途。
尝试使用像 A.B.something
这样的完全限定名称。 A
与 B
在同一个命名空间,但不在同一个变量范围内。