Initializing Member Variables
Peter Otten
__peter__ at web.de
Mon Mar 8 13:37:05 EST 2004
Scott Brady Drummonds wrote:
> I'm a Python novice and just diagnosed a problem that is confusing me. I
> wrote a class that looks like this:
>
> class Keys:
> __dict = {}
>
> def __init__(self, key):
> self.__dict[key] = key
> print('keys are now: %s' % self.__dict.keys())
>
>
> When I test this class from my Python interpreter (interactive), I see the
> following strange behavior:
>
>>>> import keys
>>>> k1 = keys.Keys('1')
> keys are now: ['1']
>>>> k2 = keys.Keys('2')
> keys are now: ['2', '1']
>>>> k3 = keys.Keys('4')
> keys are now: ['4', '2', '1']
>>>>
>
>
> Maybe this isn't strange for a Python developer, but it sure is for me. I
> thought that the "__dict = {}" line after the class declaration was
> supposed
> to initialize that member variable for each object. Obviously, that's not
> happening. Instead, that variable is retaining its value from one object
> to
> the next, like a static member variable. For what it's worth, it seems
> that this static variable behavior is not observed when using scalar
> variables. Just with dictionaries.
You've pretty much answered it yourself, except for the last sentence. The
difference is not scalars versus vectors but rebinding versus mutating.
a = {} # rebind a
a = b # rebind a
is fundamentally different from
a[key] = value # change a's value
As strings and integers are immutable you are always using only the first
pattern - it doesn't matter if you reuse the same object in several places,
because its value can never change.
> Where have I gone wrong? What is the purpose of that "initialization" in
> the Keys class? What is the correct was to initialize a class's member
> variable and guarantee that it is properly initialized for all objects?
self.__dict used in the __init__() method is misleading in your case,
because if the attribute is not found in the instance, lookup proceeds to
the class. This may have funny effects:
>>> class A:
... b = 1
...
>>> a = A()
>>> a.b
1
>>> a.b = 2 # create an instance attribute
>>> a.b # the class attribute is now shadowed...
2
>>> A.b # ...but still there
1
>>> del a.b # delete the instance attribute
>>> a.b # the class atttribute is visible again
1
Putting it all together: create the dictionary in the __init__() method
instead of the class body (and while we're at it - do you really need that
extra privacy provided by the double underscore?):
>>> class Keys:
... def __init__(self, key):
... self._dict = {}
... self._dict[key] = key
...
>>> k = Keys("first")
>>> k2 = Keys("second")
>>> k._dict
{'first': 'first'}
>>> k2._dict
{'second': 'second'}
>>>
Peter
More information about the Python-list
mailing list