Samuel M. Smith wrote: > On 06 Dec, 2005, at 20:53, Steven Bethard wrote: >> You can always shadow class-level attributes in the instance dict. >> (That's what you were doing.) If you want to (try to) replace an >> attribute in the class dict, you need to use the class object, not an >> instance object. > > I guess that's where my understanding breaks down. I thought the only > way to access class attributes was by > calling the class directly as your example indicates but __iter__ is a > class attribute that I can access from the instance > at least to read it. So what determines which class attributes get > copied to the instance and which ones don't?
When "reading" an attribute, Python looks through the namespaces in the order (instance, type). So if the attribute exists in the instance, the instance-level value is returned. If the attribute does not exist in the instance, but does exist in the class, then the class-level value is returned: >>> class C(object): ... x = 1 ... >>> inst = C() >>> inst.x 1 >>> C.x 1 >>> class C(object): ... x = 1 ... def __init__(self): ... self.x = 2 ... >>> inst = C() >>> inst.x 2 >>> C.x 1 When "writing" an attribute (i.e. using the assignment statement), Python does not try to do any namespace searching. Thus if you use the instance in an assignment statement, then it is the instance's attributes that get modified, and if you use the class in an assignment statement, then it is the class's attributes that get modififed: >>> class C(object): ... pass ... >>> inst = C() >>> inst.x = 1 >>> C.x Traceback (most recent call last): File "<interactive input>", line 1, in ? AttributeError: type object 'C' has no attribute 'x' >>> inst.x 1 >>> class C(object): ... pass ... >>> inst = C() >>> C.x = 1 >>> inst.x 1 >>> C.x 1 HTH, STeVe P.S. Note that there is an additional complication resulting from the fact that functions are descriptors: >>> class C(dict): ... pass ... >>> C.__iter__ <slot wrapper '__iter__' of 'dict' objects> >>> C().__iter__ <method-wrapper object at 0x00E74A10> Even though the C instance is accessing the __iter__ function on the class, it gets back a different value because descriptors return different values depending on whether they are accessed from a class or an instance. I don't think you need to understand this to solve your problem though, so I won't go into any more details unless you think it would be helpful. -- http://mail.python.org/mailman/listinfo/python-list