2015-02-26 3 views
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 

Moving _var в Outer не помогает - перемещение его в рамках модуля будет работать, но побеждает цель наличия классов. Итак, как это сделать?доступа атрибут базового класса в производном классе - в «области видимости класса»

EDIT: переход от Java, поэтому правила определения классов являются для меня головным скребком - будет оценен брифинг. Это работает кстати:

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

но это не вершина элегантности.

Связанные: Nested classes' scope? - но здесь мы специально хотим получить доступ к нашему родительскому классу (а не внешний типа)

EDIT2: То, что я на самом деле после того, как это _var = __class__._var -кака синтаксиса (или взломать), или объяснение как почему его там нет

ответ

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.

-1

Когда вы кладете его в метод он работает.

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

У меня такое впечатление, что все дело в инициализации.

+0

Отключить тему - я хочу получить к ней доступ в классе - не один раз при инициализации –

+0

Я не нахожу это настолько вне темы, вы всегда можете использовать staticmethod или classmethod. – pacholik

+0

Статический и классный метод будет дуть одинаково - не принимайте его лично, в этом сообществе принято удалять свой ответ, если он не совсем работает;) –

3

Python никогда не ищет имя в приложениях класса. Марк Лутц использует аббревиатуру LEGB, чтобы обобщить сферу применения в своем введении к Python (Learning 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']) 

В тот момент, вы вкладываете эти два утверждения класса под другим классом заявления они будут исключены из поиска имен, поскольку они стали частью более крупного класса заявления и, таким образом, исключаются из поиска различных областей.

+0

Нет вложенных в него классов (естественно, я рефакторинг существующего дизайн - я намерен искоренить эти классы, так что это снова вопрос любопытства). Можем ли мы каким-то образом использовать тот факт, что мы ('Derived') уже на самом деле?(Если только '_var = __class __._ var' будет компилироваться ...) –

+0

' Derived' * не имеет * _var'. Его базовый класс делает, и 'Derived._var' будет работать из-за того, как работает унаследованный поиск атрибутов. Однако правило LEGB гласит, что 'Derived' на самом деле не способ доступа к базовому классу до тех пор, пока не будет завершено определение класса (по крайней мере, при использовании оператора' class'). – chepner

+0

Принял ответ chepner для части «взлома» (поверьте мне, что я искал), - но ваш предлагает более глубокое понимание «правил определения классов». Не стесняйтесь добавлять ссылки на акроним LEGB :) –

Смежные вопросы