嵌套类的范围?

113 python scope nested class inner-classes

我试图理解Python中嵌套类的范围.这是我的示例代码:

class OuterClass:
    outer_var = 1
    class InnerClass:
        inner_var = outer_var
Run Code Online (Sandbox Code Playgroud)

类的创建没有完成,我收到错误:

<type 'exceptions.NameError'>: name 'outer_var' is not defined
Run Code Online (Sandbox Code Playgroud)

尝试inner_var = Outerclass.outer_var不起作用.我明白了:

<type 'exceptions.NameError'>: name 'OuterClass' is not defined
Run Code Online (Sandbox Code Playgroud)

我试图访问静态outer_varInnerClass.

有没有办法做到这一点?

小智 104

class Outer(object):
    outer_var = 1

    class Inner(object):
        @property
        def inner_var(self):
            return Outer.outer_var
Run Code Online (Sandbox Code Playgroud)

这与其他语言中的类似功能并不完全相同,并且使用全局查找而不是对其进行范围限定outer_var.(如果更改了名称Outer绑定的对象,则此代码将在下次执行时使用该对象.)

如果您希望所有Inner对象都具有对a的引用,Outer因为outer_var它实际上是一个实例属性:

class Outer(object):
    def __init__(self):
        self.outer_var = 1

    def get_inner(self):
        return self.Inner(self)
        # "self.Inner" is because Inner is a class attribute of this class
        # "Outer.Inner" would also work, or move Inner to global scope
        # and then just use "Inner"

    class Inner(object):
        def __init__(self, outer):
            self.outer = outer

        @property
        def inner_var(self):
            return self.outer.outer_var
Run Code Online (Sandbox Code Playgroud)

请注意,嵌套类在Python中有点不常见,并不会自动暗示类之间的任何类型的特殊关系.你最好不要筑巢.(您仍然可以设置一个类属性上OuterInner,如果你想要的.)

  • 添加你的答案可以使用哪个版本的python可能会有所帮助. (2认同)
  • @batbrat,这意味着每次执行“Inner.inner_var”时都会重新查找对“Outer”的引用。因此,如果您将名称“Outer”重新绑定到新对象,“Inner.inner_var”将开始返回该新对象。 (2认同)

eyq*_*uem 44

我想你可以做到:

class OuterClass:
    outer_var = 1

    class InnerClass:
        pass
    InnerClass.inner_var = outer_var
Run Code Online (Sandbox Code Playgroud)

您遇到的问题是由于:

块是一段Python程序文本,作为一个单元执行.以下是块:模块,函数体和类定义.
(...)
范围定义块内名称的可见性.
(...)
类块中定义的名称范围仅限于类块; 它没有扩展到方法的代码块 - 这包括生成器表达式,因为它们是使用函数作用域实现的.这意味着以下内容将失败:

   class A:  

       a = 42  

       b = list(a + i for i in range(10))
Run Code Online (Sandbox Code Playgroud)

http://docs.python.org/reference/executionmodel.html#naming-and-binding

上述方法:
函数体是代码块,方法是函数,然后在类定义中存在的函数体中定义的名称不会扩展到函数体.

根据您的情况对此进行解释:
类定义是一个代码块,然后在外部类定义中存在的内部类定义中定义的名称不会扩展到内部类定义.

  • @George注意**类A**的例子不是我的,它来自Python官方文档,我给了它链接.此示例失败,并且失败是本示例中要显示的内容.实际上``list(a + i for i in range(10))``是``list((a + i for i in range(10)))``也就是说``list(a_generator)` `.他们说**生成器**的实现范围与功能范围相似. (6认同)
  • @George:FWIW,在Python 3中,`list(...)`调用和理解都不起作用.[文档](http://docs.python.org/3/reference/executionmodel.html?highlight=naming% Py3的20绑定#naming-and-binding)也反映了这一点.它现在说"**类块中定义的名称范围仅限于类块;它不扩展到方法的代码块 - 这包括_comprehensions_和生成器表达式,因为它们是使用函数作用域实现的.**"(强调我的). (5认同)
  • 惊人.您的示例失败,声称"全局名称'a'未定义".然而,用列表理解"[a + i for i in range(10)]"成功地将Ab绑定到预期的列表[42..51]. (2认同)

Jas*_*rff 20

如果您不使用嵌套类,可能会更好.如果你必须嵌套,试试这个:

x = 1
class OuterClass:
    outer_var = x
    class InnerClass:
        inner_var = x
Run Code Online (Sandbox Code Playgroud)

或者在嵌套之前声明这两个类:

class OuterClass:
    outer_var = 1

class InnerClass:
    inner_var = OuterClass.outer_var

OuterClass.InnerClass = InnerClass
Run Code Online (Sandbox Code Playgroud)

(del InnerClass如果需要,可以在此之后.)