在派生 class 中访问基础 class 属性 - 在 "class scope" 中

Access base class attribute in derived class - in "class scope"

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 没有帮助 - 在模块范围内移动它会起作用,但会破坏具有 classes 的目的。那么该怎么做呢?

编辑:来自 Java,所以 classes 的范围规则让我头疼 - 如果能提供简报,我们将不胜感激。顺便说一句:

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

但这不是优雅的顶峰。

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

EDIT2:我真正想要的是一个类似于 _var = __class__._var 的语法(或 hack),或者关于 为什么 它不存在的解释

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

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

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

Python 从不在封闭的 class 语句中搜索名称。 Mark Lutz 在他对 Python 的介绍(学习 Python)中使用首字母缩略词 LEGB 来总结范围:Python 搜索本地范围,然后是任何封闭 def 语句的局部范围,然后是全局范围,最后是内置范围。 Class 个语句被排除在这个范围列表之外; Python 不搜索包含 class 语句的名称。

一个解决方案是取消嵌套您的 classes。在 Python 中,使用非嵌套的 classes 通常因其简单性而受到青睐。但是,当然,嵌套 classes 也是有充分理由的。为什么要嵌套 InnerBase?我想知道您是否因为在 Java 中的经验而嵌套了 class。以下内容是否也适合您?

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

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

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

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

您可以绕过 class 语句并显式调用 type

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

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