派生类中的访问基类属性 - 在“类范围”中

时间:2015-02-26 05:13:33

标签: python-2.7 static scope nested-class class-attributes

class Outer(object):
    class InnerBase(object): _var = {'foo', 'bar'}
    class Derived(InnerBase):
        _var = _var | {'baz'} # NameError: name '_var' is not defined
        _var = InnerBase._var | {'baz'} #  name 'InnerBase' is not defined
        _var = Outer.InnerBase._var | {'baz'} #  free variable 'Outer'
        # referenced before assignment in enclosing scope

Outer中移动_var并没有帮助 - 在模块范围内移动它会起作用但是会破坏课程的目的。那怎么办呢?

编辑:来自Java,所以课程的范围规则对我来说是一个令人头疼的问题 - 简报会很感激。这工作顺便说一下:

    class Derived(InnerBase): pass
    Derived._var = InnerBase._var | {'baz'}

但它并不是优雅的顶峰。

相关:Nested classes' scope? - 但在这里我们特别想要访问我们的父类(而不是外部类型)

EDIT2:我实际上是一个类似_var = __class__._var的语法(或黑客),或者为什么不存在

的解释

3 个答案:

答案 0 :(得分:3)

Python从不在封闭的类语句中搜索名称。 Mark Lutz使用首字母缩略词LEGB来概括他对Python(学习Python )的介绍中的范围:Python搜索本地范围,然后搜索任何封闭的def语句的本地范围,然后是全局范围,最后是内置范围。类范围列表中不包括类语句; Python不会为名称搜索封闭的类语句。

一种解决方案是取消嵌套您的课程。在Python中,使用非嵌套类通常是首选,因为它的简单性。但是,当然,也有很好的理由来嵌套课程。你为什么要嵌套InnerBase?我想知道你是否可能因为你在Java方面的经验而嵌套了那个类。以下是否也适合您?

class InnerBase(object):
    _var = {'foo', 'bar'}

class Derived(InnerBase):
    _var = InnerBase._var | {'baz'}

>>> Derived._var
set(['baz', 'foo', 'bar'])

在将这两个类语句嵌套在另一个类语句下的那一刻,它们将从名称搜索中排除,因为它们已成为较大类语句的一部分,因此被排除在搜索各种范围之外。

答案 1 :(得分:2)

您可以绕过class语句,并使用对type的显式调用。

class Outer(object):
    class InnerBase(object): _var = {'foo', 'bar'}
    Derived = type('Derived',
                   (InnerBase,),
                   {'_var': InnerBase._var | {'baz'}}
                  )

这是有效的,因为Derived._var未通过定义class的{​​{1}}语句中的赋值语句设置,而是从您在与{{1}相同的环境中创建的字典中导入本身。

答案 2 :(得分:-1)

当你把它放在一个方法中时,它可以工作。

    def __init__(self):
        _var = Outer.InnerBase._var | {'baz'}
        #_var = super(Outer.Derived, self)._var | {'baz'}    # or with super
        print(_var)

所以我的印象就是初始化。