sharing dictionaries amongst class instances

Peter Otten __peter__ at web.de
Mon Nov 10 13:41:42 CET 2003


Kerry Neilson wrote:

> class a:
>   x = 0
>   y = 0
> :
> 
> I suppose it's a c++ leftover thing, thinking i had to declare before I
> init.  I don't yet understand why it's different for a simple data type
> than
> it is for the list of dictionaries.  But by taking the dict_entry{} and
> my_dict[] out of the top of the class, it works without deepcopy.   

class A:
    x = 100
    y = {}

Here both assignments aren't declarations, but statements that are executed
when the module containing them is imported.

>>> A.x, A.y
(100, {})
>>>

So they are both stored in the class. Let's play a little:

>>> a = A()
>>> a.x
100

>>> a.x = 200
>>> a.x, A.x
(200, 100)
>>>

You might suppose that a.x was initialized to A.x, but that's not the case:

>>> del a.x
>>> a.x
100
>>>

See? The old value seems to reappear. When you say a.x and there is no
instance attribute, Python looks up the class attribute with the same name.
So you can use the class attribute as a kind of default value for the
instance attribute.
But beware, this technique bites you as soon as you try it with mutables:

>>> a.y["key"] = "value"

This looks the same, whether y is an instance or class attribute, and you
would not complicate client code with some detection scheme.

>>> A.y
{'key': 'value'}
>>>

Oops, there was no y attribute in the instance, so we inadvertently changed
y of the underlying class.

By the way, for the same reason you must not use mutable values as default
function arguments:

def addwords(words, wordlist=[]):
    "Bad, don't do it"
    wordlist.extend(words.split())
    return wordlist

The default wordlist is growing every time you don't provide a second
argument. The canonical Python solution is

def addwords2(words, wordlist=None):
    if wordlist is None: wordlist = []
    wordlist.extend(words.split())
    return wordlist

which creates a new wordlist when the second argument is omitted.

Peter






More information about the Python-list mailing list