关于python 2.7:派生类中的访问基类属性 – 在“类范围”中

Access base class attribute in derived class - in “class scope”

1
2
3
4
5
6
7
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并没有帮助——在模块范围内移动var会起作用,但会破坏拥有类的目的。那怎么办呢?

编辑:来自Java,所以类的范围规则对我来说是一个头疼的问题。这工作BTW:

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

但这不是优雅的顶峰。

相关:嵌套类的作用域?-但是这里我们特别想访问我们的父类(而不是外部类型)

Edt2:我实际上是一个EDCOX1,1类似的语法(或HACK),或者解释为什么它不在那里。


python从不在封闭类语句中搜索名称。Mark Lutz使用缩写legb总结了他对python(learning python)的介绍中的作用域:python搜索本地作用域,然后搜索任何包含def语句的本地作用域,然后搜索全局作用域,最后是内置作用域。类语句从此作用域列表中排除;python不搜索封闭类语句中的名称。

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

1
2
3
4
5
6
7
8
class InnerBase(object):
    _var = {'foo', 'bar'}

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

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

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


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

1
2
3
4
5
6
class Outer(object):
    class InnerBase(object): _var = {'foo', 'bar'}
    Derived = type('Derived',
                   (InnerBase,),
                   {'_var': InnerBase._var | {'baz'}}
                  )

这是因为Derived._var不是通过定义Derivedclass语句中的赋值语句设置的,而是从您在与InnerBase本身相同的环境中创建的字典导入的。


当你把它放在一个方法中,它就会起作用。

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

所以我的印象是,一切都是关于初始化的。