Global variables within classes.
Marc 'BlackJack' Rintsch
bj_666 at gmx.net
Sat Nov 10 12:39:04 EST 2007
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
More information about the Python-list
mailing list