2015-02-24 2 views
-1

По documentation: «Вообще говоря, переменные экземпляра данных, уникальных для каждого экземпляра и переменные класса предназначены для атрибутов и методов, разделяемых всеми экземплярами класса»Python переменные области видимости класса не в соответствии с документацией

>>> class Dog: 
... kind='canine' 
... 
... def __init__(self, name): 
...  self.name = name 
... 
>>> d = Dog('Fido') 
>>> e = Dog('Buddy') 
>>> d.name 
'Fido' 
>>> e.name 
'Buddy' 
>>> d.kind 
'canine' 
>>> e.kind 
'canine' 
>>> d.kind='cat' # changed supposedly shared variable to cat 
>>> d.kind # OK here 
'cat' 
>>> e.kind # Not expected output (should be cat as per documentation) 
'canine' 

Я что-то упускаю?

+0

вы изменили его для объекта, изменение для одного объекта не отразится на всех объектах. Объект является экземпляром класса – Hackaholic

+0

Это может быть не лучший выбор для «дублирования», но вопрос обычно возникает. –

ответ

1

Вы устанавливаете атрибут экземпляра, маскируя атрибут класса:

d.kind = 'cat' 

Если вы установите его на классе, а это будет видно на всех случаях:

Dog.kind = 'cat' 

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

Используйте vars() function, чтобы увидеть разницу:

>>> class Dog: 
...  kind = 'canine' 
...  def __init__(self, name): 
...   self.name = name 
... 
>>> d = Dog('Fido') 
>>> e = Dog('Buddy') 
>>> vars(d) 
{'name': 'Fido'} 
>>> 'kind' in vars(d) 
False 
>>> vars(Dog) 
mappingproxy({'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Dog' objects>, 'kind': 'canine', '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None, '__init__': <function Dog.__init__ at 0x10084bbf8>}) 
>>> 'kind' in vars(Dog) 
True 
>>> d.kind 
'canine' 
>>> d.kind = 'cat' 
>>> d.kind 
'cat' 
>>> vars(d) 
{'name': 'Fido', 'kind': 'cat'} 
>>> Dog.kind 
'canine' 

vars() функция показывает атрибуты, доступные как на классе и один из экземпляров. Назначая d.kind, новый атрибут появляется в словаре имен для этого экземпляра, и оттуда все поисковые запросы в этом экземпляре возвращают этот атрибут и не попадают в класс.

4

Выполнение d.kind='cat' создает новый атрибут экземпляра с именем kind и устанавливает его в 'cat'. Более того, это затмевает атрибут класса.

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

Dog.kind='cat' 
+0

Спасибо. Короткие и сладкие! – Tarik

1

Если вы instance.attr = "blah", вы всегда должен быть установлен атрибут экземпляра, даже если уже есть атрибут класса с тем же именем. Сделав d.kind = "cat", вы создали экземпляр с именем kind, который теняет переменную класса kind.

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