As per documentation: "Generally speaking, instance variables are for data unique to each instance and class variables are for attributes and methods shared by all instances of the class"
>>> 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'
Am I missing something?
-
you have change it for object, changing for one object will not reflect in all object. Object is an instance of classHackaholic– Hackaholic2015年02月24日 19:23:08 +00:00Commented Feb 24, 2015 at 19:23
-
This may not be the best choice for 'duplicate' marking, but the question does come up commonly.Karl Knechtel– Karl Knechtel2015年02月24日 19:27:23 +00:00Commented Feb 24, 2015 at 19:27
3 Answers 3
Doing d.kind='cat'
creates a new instance attribute named kind
and sets it to 'cat'
. Moreover, this overshadows the class attribute.
In order to change the class attribute, you need to set it on the class itself and not an instance:
Dog.kind='cat'
If you do instance.attr = "blah"
, you always set an instance attribute, even if there is already a class attribute of the same name. By doing d.kind = "cat"
you created an instance attributed called kind
which shadows the class variable called kind
.
You are setting an instance attribute, masking the class attribute:
d.kind = 'cat'
If you set it on the class instead it'll be visible on all instances:
Dog.kind = 'cat'
You cannot set class attributes by assigning to the name on instances. If you could, you would never be able to set instance attributes.
Use the vars()
function to see the difference:
>>> 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'
The vars()
function reveals the attributes available on both the class and one of the instances. By assigning to d.kind
, the new attribute appears in the dictionary of names for that instance, and from there on out all lookups on that instance will return that attribute and not fall through to the class.