Although the accepted anwer is spot on, I would like to add a bit description.
Let's do a small exercise
first of all define a class as follows:
class A:
temp = 'Skyharbor'
def __init__(self, x):
self.x = x
def change(self, y):
self.temp = y
So what do we have here?
- We have a very simple class which has an attribute
temp
which is a string
- An
__init__
method which sets self.x
- A change method sets
self.temp
Pretty straight forward so far yeah? Now let's start playing around with this class. Let's initialize this class first:
a = A('Tesseract')
Now do the following:
>>> print(a.temp)
Skyharbor
>>> print(A.temp)
Skyharbor
Well, a.temp
worked as expected but how the hell did A.temp
work? Well it worked because temp is a class attribute. Everything in python is an object. Here A is also an object of class type
. Thus the attribute temp is an attribute held by the A
class and if you change the value of temp through A
(and not through an instance of a
), the changed value is going to be reflected in all the instance of A
class.
Let's go ahead and do that:
>>> A.temp = 'Monuments'
>>> print(A.temp)
Monuments
>>> print(a.temp)
Monuments
Interesting isn't it? And note that id(a.temp)
and id(A.temp)
are still the same.
Any Python object is automatically given a __dict__
attribute, which contains its list of attributes. Let's investigate what this dictionary contains for our example objects:
>>> print(A.__dict__)
{
'change': <function change at 0x7f5e26fee6e0>,
'__module__': '__main__',
'__init__': <function __init__ at 0x7f5e26fee668>,
'temp': 'Monuments',
'__doc__': None
}
>>> print(a.__dict__)
{x: 'Tesseract'}
Note that temp
attribute is listed among A
class's attributes while x
is listed for the instance.
So how come that we get a defined value of a.temp
if it is not even listed for the instance a
. Well that's the magic of __getattribute__()
method. In Python the dotted syntax automatically invokes this method so when we write a.temp
, Python executes a.__getattribute__('temp')
. That method performs the attribute lookup action, i.e. finds the value of the attribute by looking in different places.
The standard implementation of __getattribute__()
searches first the internal dictionary (dict) of an object, then the type of the object itself. In this case a.__getattribute__('temp')
executes first a.__dict__['temp']
and then a.__class__.__dict__['temp']
Okay now let's use our change
method:
>>> a.change('Intervals')
>>> print(a.temp)
Intervals
>>> print(A.temp)
Monuments
Well now that we have used self
, print(a.temp)
gives us a different value from print(A.temp)
.
Now if we compare id(a.temp)
and id(A.temp)
, they will be different.