On Sat, 10 Nov 2007 18:53:08 +0200, Donn Ingle wrote: > Included again for clarity: >>> class Test: >>> attribute = "original value" >>> >>> class Bob: >>> def __init__(self): >>> self.ref = Test() >>> >>> class Jim: >>> def __init__(self): >>> self.ref = Test() >>> >>> b = Bob() >>> j = Jim() >>> >>> print b.ref.attribute #prints "original value" >>> b.ref.attribute = "haschanged" >>> ## Where is the value "haschanged" going here? >> >> To *instance* of `Test` you created and bound to `b.ref`. >> > I don't follow you here. I *think* you are saying I created a *new* (on the > fly) ref within b that is also called 'attrib', so that it's kind of > shadowing the original 'attribute' ref (the so-called class attribute.) > ?
In the `__init__()` of `Bob` you created an instance of `Test`. You can't create a `ref`, that's just a name of an attribute on `Bob` instances. Then you bind the attribute `attribute` of that instance to the string "haschanged". This assignment creates the attribute because `Test` *instances* don't have such an attribute. And yes this `attribute` shadows the class `attribute` as the lookup rules are instance -> class -> base classes. >>> print b.ref.attribute # print "haschanged" >>> >>> print j.ref.attribute #prints "original value" >>> ## If it changed and an attribute of the Class, then >>> ## why is it back to "original value" ? >> >> Because the *instance* of `Test` bound to `j.ref` does not have >> `attribute` it is looked up in the *class* `Test`. > Okay, I sort of see that. It's not a property of 'j' so it looks upwards > into the class. Its not an attribute of `j.ref`! Here's a little ASCII art showing the situation after your code was executed:: Names | Objects -------+--------------------------------------------- | +----------+ Test ------>|<class> | +----------------+ | |attribute----------->|<str> | | +----------+ |"original value"| | +----------------+ | | +------+ j --------->|<Joe> | +----------+ | |ref ---->|<Test> | | +------+ +----------+ | | | +------+ b --------->|<Bob> | +----------+ | |ref ---->|<Test> | +------------+ | +------+ |attribute---->|<str> | | +----------+ |"haschanged"| | +------------+ On the left are the names in the module's namespace and on the right are the objects in memory. From the `Test` objects there's also a reference to the `class` that's bound to the name `Test` in the Module that is not shown in the "drawing" but necessary to look up attributes in the class of the instances. > This is kind of weird. It's not clear like Python usually is. Is this > something intentional or did it 'fall through the cracks'? I mean, can one > rely on it or will it be 'fixed'? Don't think so. It's a surprise for many but then class attributes are not that common in code or they even use this "gotcha" for immutable default values. As long a the value isn't changed the default value is just referenced from the class then and not every instance. Ciao, Marc 'BlackJack' Rintsch -- http://mail.python.org/mailman/listinfo/python-list