嵌套类的范围?

时间:2009-11-19 18:53:06

标签: python class scope nested inner-classes

我正在尝试理解Python中嵌套类的范围。这是我的示例代码:

class OuterClass:
    outer_var = 1
    class InnerClass:
        inner_var = outer_var

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

<type 'exceptions.NameError'>: name 'outer_var' is not defined

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

<type 'exceptions.NameError'>: name 'OuterClass' is not defined

我正在尝试从outer_var访问静态InnerClass

有办法做到这一点吗?

6 个答案:

答案 0 :(得分:103)

class Outer(object):
    outer_var = 1

    class Inner(object):
        @property
        def inner_var(self):
            return Outer.outer_var

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

如果您希望所有Inner个对象都引用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

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

答案 1 :(得分:43)

我认为你可以做到:

class OuterClass:
    outer_var = 1

    class InnerClass:
        pass
    InnerClass.inner_var = outer_var

您遇到的问题是由于:

  

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

   class A:  

       a = 42  

       b = list(a + i for i in range(10))
     

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

以上表示:
函数体是代码块,方法是函数,那么在类定义中存在的函数体定义的名称不会扩展到函数体。

根据你的情况解释这个:
类定义是一个代码块,然后在外部类定义中出现的内部类定义中定义的名称不会扩展到内部类定义。

答案 2 :(得分:20)

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

x = 1
class OuterClass:
    outer_var = x
    class InnerClass:
        inner_var = x

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

class OuterClass:
    outer_var = 1

class InnerClass:
    inner_var = OuterClass.outer_var

OuterClass.InnerClass = InnerClass

(如果需要,您可以del InnerClass之后。)

答案 3 :(得分:4)

最简单的解决方案:

class OuterClass:
    outer_var = 1
    class InnerClass:
        def __init__(self):
            self.inner_var = OuterClass.outer_var

它要求你明确,但不需要太多努力。

答案 4 :(得分:1)

在Python中,可变对象作为引用传递,因此您可以将外部类的引用传递给内部类。

class OuterClass:
    def __init__(self):
        self.outer_var = 1
        self.inner_class = OuterClass.InnerClass(self)
        print('Inner variable in OuterClass = %d' % self.inner_class.inner_var)

    class InnerClass:
        def __init__(self, outer_class):
            self.outer_class = outer_class
            self.inner_var = 2
            print('Outer variable in InnerClass = %d' % self.outer_class.outer_var)

答案 5 :(得分:0)

所有解释都可以在 Python文档Python教程

中找到

首次出现错误<type 'exceptions.NameError'>: name 'outer_var' is not defined。解释是:

  

没有从方法中引用数据属性(或其他方法!)的简写。我发现这实际上增加了方法的可读性:在浏览方法时,没有可能混淆局部变量和实例变量。

引自 Python教程9.4

对于您的第二个错误<type 'exceptions.NameError'>: name 'OuterClass' is not defined

  

当正常保留类定义(通过结尾)时,会创建一个类对象。

引用自 Python教程9.3.1

因此,当您尝试inner_var = Outerclass.outer_var时,Quterclass尚未创建,这就是为什么name 'OuterClass' is not defined

对您的第一个错误进行更详细但乏味的解释:

  

虽然类可以访问封闭函数的作用域,但它们不起作用   作为嵌套在类中的代码的封闭范围:Python搜索封闭的函数   对于引用的名称,但从不包含任何封闭的类。也就是说,类是本地范围   并且可以访问封闭的本地范围,但它不能作为封闭的本地范围   进一步嵌套代码。

引用 Learning.Python(5th).Mark.Lutz