2012-05-12 5 views
3

Вот немного нового вопроса Python о переменных экземпляра.Экземпляр класса Python __dict__ не содержит всех переменных экземпляра. Зачем?

Рассмотрим следующий Python определение класса 2,7:

class Foo(object): 
    a = 1 

    def __init__(self): 
      self.b = 2 

    def __repr__(self): 
      return "%s" % self.__dict__ 

Теперь, когда я создаю экземпляр Foo, Foo.__dict__ содержит b, но не a.

>>> x=Foo() 
>>> x 
{'b': 2} 
>>> dir(x) 
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__module__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'a', 'b'] 
>>> x.__dict__ 
{'b': 2} 

И здесь я подумал, что у меня довольно хорошее понимание Пути Питона.

В чем разница между x.a и x.b? Насколько я могу судить, это обе переменные экземпляра.

Редактировать: OK, перечитывая Python docs я вижу, что Foo.a является атрибутом класса, а не переменной экземпляра. Hm ... Я предполагаю, что путаница происходит из-за того, что я могу назначить новое значение x.a, а новое значение влияет только на экземпляр x. Я полагаю, что теперь я накладываю переменную-член поверх атрибута Foo.a:

>>> y=Foo() 
>>> y.a = 2 
>>> y 
{'a': 2, 'b': 2} 
>>> x 
{'b': 2} 
>>> x.a 
1 
>>> z=Foo() 
>>> z 
{'b': 2} 
>>> z.a 
1 
>>> Foo.a 
1 
>>> x.a 
1 
>>> y.a 
2 

Итак, теперь я перезаписать предыдущее значение Foo.a, и это влияет на все случаи Foo, которые не псевдонимами Foo.a:

>>> Foo.a=999 
>>> x.a 
999 
>>> y.a 
2 
+0

Следует также отметить, что это не хорошая практика, чтобы полагаться на '__dict__' слишком много: clases с помощью' __slots__' и расширения классов (от C или Cython) не кладут все в там. Большинство применений могут быть заменены некоторой комбинацией 'getattr',' setattr', 'hasattr' и' dir'. – Dougal

+0

@ Dougal: Спасибо за этот совет - я увидел это на другом ответе здесь, на StackOverflow, но это хорошее подкрепление. – Inactivist

ответ

5

Ваш a не является переменной экземпляра. Вы определили его как часть класса.

>>> class Foo(object): 
... a = 1 
... 
>>> Foo.a 
1 

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

3

a не является атрибутом экземпляра, это атрибут класса ,

+0

Да, но если я присваиваю новое значение 'x.a', это влияет только на экземпляр' x'. Если это атрибут класса, почему изменение значения 'x.a' не влияет на все экземпляры' Foo'? – Inactivist

+1

Потому что вы назначили его на экземпляр. – kindall

+0

Да, я вижу это сейчас. Я пропустил это при первом чтении документов. Спасибо за помощь! – Inactivist

0

Это может помочь вам?

>>> class X(object): 

    def __getattribute__(self, name): 
     print name 
     return object.__getattribute__(self, name) 


>>> l = dir(X()) 
__dict__ 
__members__ 
__methods__ 
__class__ 
>>> l 
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] 
Смежные вопросы