为什么一个class-inside-a-class不在另一个class-inside-a-class的范围内?

时间:2016-04-07 16:02:17

标签: python python-3.x scoping

请考虑以下代码:

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的设计中有意义呢?

2 个答案:

答案 0 :(得分:4)

PEP 227中所述,类主体的范围不能从嵌套在其中的其他范围内获得。因此,在您的示例中获得B的NameError的原因与在这种情况下获得NameError的原因相同:

class Foo(object):
    x = 88
    def foo(self):
        print(x)

在类体中定义的函数(即方法)无法访问类体范围;嵌套类(或嵌套在那些中的函数)也没有。

A.B.derp有效,因为A位于全球范围内,且始终可以访问。

但是,请注意,如果您尝试在类体中直接使用它,即使A.B.derp也无效:

class A(object):
    class B(object):
        derp = 88
    class SubA(object):
        stuff = A.B.derp

这不起作用,因为引用A.B.derp的行在创建A的过程中执行,因此A尚不存在且无法引用。< / p>

答案 1 :(得分:1)

虽然类定义了一个新的命名空间,但它们不会为方法体内使用的名称创建范围。在提及它们时,名称必须完全合格。这是self.somethingcls.something的用途。

尝试使用A.B.something等完全限定名称。 AB位于同一名称空间中,但不在同一变量范围内。