Why do class methods share mutable defaults between instances?

Ron Teeter ron.teeter at supplysolution.com
Tue Apr 30 18:50:25 EDT 2002


Asked and answered... little more digging around and I found this...

Python documentation, section 4.7.1, excerpt:
"""
Important warning: The default value is evaluated only once. This makes a
difference
when the default is a mutable object such as a list or dictionary. For example,
the following function accumulates the arguments passed to it on subsequent
calls:

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)
This will print


[1]
[1, 2]
[1, 2, 3]

If you don't want the default to be shared between subsequent calls, you can
write
the function like this instead:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L
"""

Chalk it up to insufficient familiarity with default value initialization.

Thanks anyway,

Ron Teeter

> -----Original Message-----
> From: python-list-admin at python.org
> [mailto:python-list-admin at python.org]On Behalf Of Ron Teeter
> Sent: Tuesday, April 30, 2002 6:12 PM
> To: python-list at python.org
> Subject: Why do class methods share mutable defaults between
> instances?
>
>
> Greetings,
>
> Today I made a rather perplexing discovery.  It appears that
> mutable defaults
> in class methods are shared between instances.  Here is a
> simple example of
> the scenario.
>
> class Demo:
>     def __init__(self,name,dict={},list=[]):
>         self.name = name
>         self.dict = dict
>         self.list = list
>         self.dict[name] = name
>         self.list.append(name)
>
> def dump(name,dict={},list=[]):
>     print name,dict,list
>
> for name in ['A1','B1','C1']:
>     tmp = Demo(name)
>     dump(tmp.name,tmp.dict,tmp.list)
>
> >>>
> A1 {'A1': 'A1'} ['A1']
> B1 {'B1': 'B1', 'A1': 'A1'} ['A1', 'B1']
> C1 {'C1': 'C1', 'B1': 'B1', 'A1': 'A1'} ['A1', 'B1', 'C1']
> >>>
>
> My intent was that each time Demo was instanciated a new
> dictionary would be
> assigned to 'dict' if there was no corresponding argument.
> However, the
> behavior is as though the {} were replaced with a class constant.
>
> In order to avoid this behavior I had to reorganize Demo as follows:
>
> class Demo2:
>     def __init__(self,name,dict=None,list=None):
>         if dict==None:
>             dict = {}
>         if list==None:
>             list = []
>         self.name = name
>         self.dict = dict
>         self.list = list
>         self.dict[name] = name
>         self.list.append(name)
>
> I am wondering if this is a bug or a subtle usage error on my
> part.  I would
> expect that syntax on functions would be valid for class
> methods as well, but
> in this case you get drastically different behaviors.
>
> Thanks,
>
> Ron Teeter
>
>
>






More information about the Python-list mailing list