2015-09-14 1 views
0

В Python (2.7) можно использовать вложенные объявления классов, которые иногда удобны для организации локальных классов.Обратитесь к объекту в родительском классе из вложенного класса в Python

Однако я не могу понять, как ссылаться на класс в родительском классе, поэтому я могу извлечь из него.

Минимальный пример этого:

class A(object): 
    class B(object): 
     pass 

    class C(object): 
     class D(A.B): # <-- fails with "NameError: name 'A' is not defined" 
      pass 

Как я могу сделать класс D вывести из класса B, учитывая вложенную структуру декларации класса?

ответ

1

Вы не можете. Вы не можете ссылаться на него как A.B, так как A еще не определен (вы находитесь в середине определения), и вы не можете ссылаться на него как B, потому что в соответствии с PEP 227, имена в классе не доступны:

Имена в классе не доступны. Имена разрешены в самой внутренней охватывающей функциональной области. Если определение класса происходит в цепочке вложенных областей, процесс разрешения пропускает определения классов . Это правило предотвращает нечетные взаимодействия между атрибутами класса и доступом к локальной переменной. Если в определении класса происходит привязка имени , он создает атрибут на результирующего объекта класса. Чтобы получить доступ к этой переменной в методе или в функции, вложенной в метод, необходимо использовать ссылку атрибута либо через self, либо через имя класса.

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

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

Edit: если вы действительно, действительно хотите, чтобы ваша иерархия классов выглядеть следующим образом, вы можете просто «обезьяна патч» A:

class A(object): 
    class B(object): 
     pass 

class _C(object): 
    class D(A.B): 
     pass 

A.C = _C 
+1

Ты пятно на о рефакторинге: B не должен быть частью А. Но я все еще хотел знать, можно ли это написать. (Я нахожу его несколько неудовлетворительным, что это не так.) – kaymes