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 -- http://mail.python.org/mailman/listinfo/python-list