2014-10-23 3 views
1

Я пытаюсь понять вложение пространств имен в python 2.7.пространство имен для класса внутри класса в python

Рассмотрим следующий не-рабочий код:

class c(object): 
    def debug(self): 
    print globals(),locals() 
    print x,y 

class a(object): 
    x=7 
    def __init__(self): 
    self.y=9 
    class b(object): 
     def debug(self): 
     print globals(),locals() 
     print x,y 
    class d(c): 
     pass 

Как получить доступ к переменным х и у, от звонков

a().b().debug() 
a.b().debug() 
a().d().debug() 
a.d().debug() 

Ни один из них не кажется, в состоянии видеть ни х, ни у.

EDIT после обсуждения, кажется, что то, что я хочу (избегаю ссылки на глобальные), может быть достигнуто только путем явного расширения информации о вложенных классах. К примеру

class a(object): 
    # 
    @classmethod 
    def _initClass(cls): 
    for v in dir(cls): 
     if type(cls.__dict__[v])==type: 
     setattr(cls.__dict__[v],'vader',cls) 
    # 
    x=7 
    class b(object): 
    def debug(self): 
     print b.vader.x 
    class d(c): 
    pass 

a._initClass() 

И даже этот метод не кажется, полезно для получения доступа к переменной экземпляра, как задумано в а(). Д(). Отладочный последовательность.

+0

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

+0

@ Давид хорошо, оба были полезны, но на самом деле убедить меня пойти другим путем и отказаться от классового гнездования. – arivero

ответ

1

Martijn уже дал хороший ответ, но я возьму себе удар.

Как сказал Мартин, декларации классов выполняются скорее как одноразовые функции с их собственной локальной областью, когда их модуль сначала импортируется. Независимо от того, что осталось в этой локальной области, после того, как все в объявлении класса было выполнено, используется как словарь класса. Итак, x, __init__, b и d все в конечном итоге являются атрибутами объекта класса a.То же самое относится к вашим классам b и d; их тела выполняются, когда модуль импортируется, а оставшиеся локальные области используются в качестве их словарей.

Причина, по которой ваш код не работает, заключается в том, что к моменту выполнения метода debug единственными областями, о которых он знает, являются глобальная область действия и ее собственная локальная область. В python методы не подразумевают включение словаря экземпляра класса как часть их области действия, как в языках C++. Экземпляр класса доступен явно как аргумент self, который появляется в списке аргументов (следовательно, ядро ​​«jen» Python лучше, чем неявное »- попробуйте import this в консоли python).

Кроме того, это не имеет значения, действительно ли вы экземпляр a перед обращением и инстанцирования других классов b и d на a так b и d оба класса атрибуты a. Таким образом, python может успешно получить b и d либо из экземпляра a, либо для прямой ссылки на объект класса a.

+0

ok , я могу добавить явно на 'b' и' d' то, что a является его предыдущим пространством имен? Somthing как 'self ['b']. Vader = self' на уровне класса? – arivero

+1

@arivero Не совсем уверен, что вы имеете в виду, можете ли вы попытаться изменить свой вопрос? –

+0

Я думал ... какой-то метод класса работает после определения класса 'a' и передает информацию. Хорошо, попробуем ответить. – arivero

4

class объектов не создать область; классы класса выполняются только один раз и отбрасываются, а локальное пространство имен создает атрибуты класса. Классные тела никогда не участвуют во вложенных областях; они полностью игнорируются при разрешении нелокальных имен.

Таким образом, ваш x = 7 не является именем, которое мог бы получить доступ к вложенному классу b (или его методам). Вместо этого это атрибут класса на a. Доступ к a.x будет работать. y - атрибут экземпляра, и вам нужно будет иметь ссылку на экземпляр, чтобы он был доступен в любом месте.

Обратите внимание, что это относится к class b; это атрибут класса на a сейчас, точно так же, как x - это атрибут класса.

Нет ничего особенного в вашем классе b, кроме как вы ссылаетесь на объект класса. Просто потому, что вы создали экземпляр a, это не означает, что b имеет любой привилегированный доступ к нему; a().b() не создает отношения между экземплярами. Вы можете:

b = a.b 
b_instance = b() 

и не было никакой разницы. Вы могли бы даже сделать:

a.b.a = a 
a.b.a() 

и мир не будет взорваться! (воображают, что).

+1

Не могу поверить, что я задаю вопрос Мартину Питеру, но ... не является ли 'y' внутри' a .__ init__' атрибутом экземпляра 'a'? Чтобы быть ясным, я смотрю на строку 'self.y = 9'. Значит, это не было бы видно как 'a(). Y'? –

+2

@JohnY: ++++ ИЗ ОШИБКИ CAFFEINE ++++ REDO FROM START ++++ * fzzzwt * –

+0

Действительно, я попросил как для a.b(), так и a(). B() рассмотреть случай y. – arivero