2014-09-30 4 views
0

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

Вот код:

class Food: 
    kind = 'fruit' 
    def __init__(self, name): 
     self.name = name 

a = Food('tomato') 
b = Food('cabbage') 

print 'a ->', a.kind 
print 'b ->', b.kind 
print 'change a\'s kind' 
a.kind = 'veg' 
print 'a ->', a.kind 
print 'b ->',b.kind 
print 'change kind in the class' 
Food.kind = 'meat' 
print 'a ->', a.kind 
print 'b ->', b.kind 

Выход я получил это:

a -> fruit 
b -> fruit 
change a's kind 
a -> veg 
b -> fruit 
change kind in the class 
a -> veg 
b -> meat 

Это последний результат, который ставит меня в тупик. Если я правильно назвал «добрый» атрибут класса, то, когда я изменил его в классе с помощью «Food.kind =», он должен изменить его для обоих экземпляров. Фактически я ожидал, что он изменится, когда я дам ему новое значение через один из экземпляров, но он только изменил его в одном. Что мне здесь не хватает?

+1

Проверьте следующей ссылке: http://www.toptal.com/python/python-class-attributes-an-overly- тщательный путеводитель. В нем объясняется, как атрибуты класса и атрибуты экземпляра работают в Python. – mvillaress

+0

Пока вы не назначили 'a.kind = 'veg'', атрибут' kind' не существует в экземпляре и ссылается на переменную класса. Если вы хотите, чтобы он возвращался обратно к переменной класса, тогда 'del a.kind', и вы снова получите« мясо »для обоих. – sberry

ответ

0

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

theThing.value = 1; // bad 
Thing.value = 1; // good 

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

При написании в поле, поле написано всегда объект, на который был сделан ссылка - будь то экземпляр или класс. Например:

theThing.value = 1 # creates an instance field if one does not exist 
Thing.value = 1 # creates a class field if one does not exist 

Таким образом, при чтении значения kind: a.kind всегда будут считывать поле экземпляра (если поле не удаляются); и b.kind всегда будет читать поле класса (если не создано поле экземпляра).

1

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

>>> a.kind = 'veg' 
>>> a.__dict__ 
{'kind': 'veg', 'name': 'tomato'} 
>>> b.__dict__ 
{'name': 'cabbage'} 

Поскольку нет базовых классов здесь атрибут поиска остановится сразу после Food для несуществующих признаков, приводящих к AttributeError.

>>> a.foo 

Traceback (most recent call last): 
    File "<pyshell#6>", line 1, in <module> 
    a.foo 
AttributeError: Food instance has no attribute 'foo' 

Обратите внимание, что в новых классовspecial methods всегда ищется в случаях не класс. Но так как вы используете класс старого стиля (удален в Python 3), это не так. Но рекомендуется всегда использовать классы нового стиля (наследуем от object в Python 2).

Вы должны прочитать: атрибуты New-style and classic classes.


* Mutable класс (списки, ДИКТ и т.д.) являются одним исключением здесь, делают в месте операции на них из любого экземпляра или класса будут отражены всюду в классе и другие случаи (если экземпляр не определен новый атрибут с таким же именем):

class Food: 
    kind = [] 
    def __init__(self, name): 
     self.name = name 

a = Food('tomato') 
b = Food('cabbage') 
b.kind = [] 
a.kind.append(10) 
Food.kind.append(20) 
print a.kind #[10, 20] 
print b.kind #[] b.kind points to a different object due to the assignment above 
print Food.kind #[10, 20] 
Смежные вопросы