Python attributes
I found the recent post of my friend Vassilios Karakoidas about Python rather stimulating, in the sense that it was a good opportunity for me to remember a little python after a long while…
The basic class definition in the above-mentioned post is:
class k:
i = "foo"
def get(self):
return k.i
and the discussion in the post goes about the strange character of that ‘i’ attribute. Let me clarify things a little by providing some facts:
- The ‘i’ is defined as a class attribute, meaning that all instances of the class see the same value for ‘i’.
- Outside the class definition, you can access ‘i’ by simply typing ‘k.i’ without the need to create a new instance, as in ‘k().i’.
- Python gives us the ability to create a new attribute for an existing instance on-the-fly, without having to define it in the class constructor.
- If, probably by mistake or (as in the above post) on purpose, and according to fact 3, you decide to create an instance attribute with the same name as the class attribute, then the two ones co-exist and you need to be more precise when trying to access each of them.
With the rules above in mind. let’s play a little:
We print the value of the class attribute ‘i’, directly from the class:
>>k.i
'foo'
We create two instances and try to access the class attribute ‘i’ on both of them:
>> a=k(); b=k(); a.i; b.i
'foo'
'foo'
This is normal behaviour, since the class attribute ‘i’ is visible to any instance of the class. Now the tricky part: What if we try to change the class attribute ‘i’ via one of the instances, let’s say ‘a’:
>>a.i = 'foobar'; a.i; b.i;
'foobar'
'foo'
Oops!!! what hase gone wrong? Did we or did we not change ‘i’? Well, matters are simple. According to fact 3, what we actually did was to create an instance attribute with same name ‘i’ for the instance ‘a’. This creation of course, doesnot propagate to instance ‘b’! Now, for instance ‘a’, the instance attribute ‘i’ shadows the class attribute ‘i’, which of course we have not changed and remains the same:
>> k.i
'foo'
According to fact 4, in order to be able to access both the class attribute and the instance attribute, we just need to be more precise:
>> a.__class__.i
'foo'
>> a.i
'foobar'
And, by the way, did you notice that Python lets you write more that one statement in a line?
Tags: python