Implied instance attribute creation when referencing a class attribute

David Wahler dwahler at gmail.com
Mon Jan 16 23:22:22 EST 2006


Russell Warren wrote:
> Not true as above.  The longhand for 'self.I += 1' is 'self.I = self.I
> + 1', which normally needs self.I to exist due to the RHS of this.

Try this:

>>> class foo(object):
...   I = 1
...   def __init__(self):
...     print self.__dict__
...     self.I = self.I + 1
...     print self.__dict__
...
>>> a=foo()
{}
{'I': 2}


Notice that the result is the same! The catch is that the two
occurrences of "self.I" occur in different contexts -- on the left-hand
side of an assignment, and in an expression -- and are therefore
subject to different lookup rules. Specifically, evaluation of "self.I"
is delegated from instances to their classes and superclasses, while
assignment is not.

As an expression, "self.I" first tries and fails to look up
self.__dict__['I']; then, finding foo.__dict__['I'] to be present, it
returns that (1) instead. When the result of the expression is then
assigned to self.I, no delegation takes place and the value 2 is stored
in self.__dict__['I'].

A note of caution: you might be tempted to think that with objects such
as lists, which implement the __iadd__ method, no assignment would take
place. This is actually not the case -- it works exactly the same way!
To use another variation of your example:


>>> class foo(object):
...   lst = ['a','b','c']
...   def __init__(self):
...     print self.__dict__
...     self.lst += [1,2,3]
...     print self.__dict__
...
>>> a=foo()
{}
{'lst': ['a','b','c',1,2,3]}
>>> foo.l
['a','b','c',1,2,3]
>>> id(foo.lst) == id(a.lst)
True

The list is mutated in-place, but there is _also_ an implicit
assignment to self.lst. In other words, it expands to:

self.lst = self.lst.__iadd__([1,2,3])

Normally this implicit assignment doesn't matter, since the context the
variable is stored into is the same one it was retrieved from. It's
only in situations like yours where it becomes important.

-- David




More information about the Python-list mailing list