3
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

将 _var 移入Outer没有帮助 - 将其移入模块范围会起作用,但会破坏拥有类的目的。那么该怎么做呢?

编辑:来自 Java,所以类的范围规则对我来说是一个令人头疼的问题 - 简报将不胜感激。顺便说一句,这有效:

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

但这不是优雅的顶峰。

相关:嵌套类的范围?- 但是这里我们特别想访问我们的父类(而不是 Outer 类型)

EDIT2:我实际上追求的是类似_var = __class__._var的语法(或hack),或者解释为什么它不存在

4

3 回答 3

3

Python 从不在封闭类语句中搜索名称。Mark Lutz在他的 Python 简介( Learning Python )中使用首字母缩略词LEGB来总结作用域:Python 搜索局部作用域,然后搜索任何封闭语句的局部作用域,然后是全局作用域,最后是内置作用域。类语句不包括在此范围列表中;Python 不会在封闭类语句中搜索名称。def

一种解决方案是取消嵌套类。在 Python 中,由于其简单性,通常首选使用非嵌套类。但是,当然,嵌套类也有充分的理由。你为什么要嵌套InnerBase?我想知道您是否可能因为您在 Java 方面的经验而嵌套了该类。以下内容也对您有用吗?

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

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

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

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

于 2015-04-25T16:21:38.037 回答
2

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

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

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

于 2015-04-25T17:00:46.813 回答
-1

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

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

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

于 2015-04-25T13:41:35.923 回答