Bizarre behavior with mutable default arguments

bukzor workitharder at gmail.com
Sat Dec 29 23:21:08 EST 2007


Just for completeness, the mutable default value problem also affects
classes:

class c:
    def __init__(self, list = []):
        self.list = list
        self.list.append("LIST END")
    def __repr__(self):
        return "<Class a: %s>" % self.list

>>> import example2
>>> print example2.c()
<Class a: ['LIST END']>
>>> print example2.c([])
<Class a: ['LIST END']>
>>> print example2.c()
<Class a: ['LIST END', 'LIST END']>
>>> print example2.c([])
<Class a: ['LIST END']>

Again, we get different results if we supply an argument that is
identical to the default value. There are many instances in the
standard library where class values are assigned directly from the
initializer, which has list or dict default values, so there is chance
for errors cropping up here.

The error scenario is this:
    1. Use a mutable value as default value in a class constructor.
    2. Assign class property from constructor arguments.
    3. Instantiate class using default value.
    4. Modify class property in place.
    5. Instantiate (again) class using default value.

The second instance will behave strangely because data from the first
instance has leaked over. The standard library is not affected because
it avoids one of these five steps. Most classes simply don't have
mutable default values (1). Those that do generally treat them as read-
only (4). Some classes are not useful using the default values (3).
Some classes are not useful to be instantiated twice (5). The classes
that don't avoid the problem at one of these four steps have to avoid
it at (2) by using one of the three above patterns.

--Buck



More information about the Python-list mailing list