Strange Behavior

Steven D'Aprano steve at REMOVE.THIS.cybersource.com.au
Mon Oct 16 10:51:15 EDT 2006


On Mon, 16 Oct 2006 07:26:05 -0700, abcd wrote:

> class Foo:
>     def __init__(self, name, data=[]):

The binding of the name "data" to the empty list happens at compile time,
not runtime.

>         self.name = name
>         self.data = data
> 
>     def addData(self, val):
>         self.data.append(val)

Every time you call addData on an instance, it appends to the same list.
So all instances created with Foo(name) share the same list in data.

Think of it like this:

some_list = []
x = Foo("fred", some_list)
y = Foo("wilma", some_list)

Isn't it obvious now that both instances share the same list? That x.data
and y.data don't just have the same value, but are the same object? The
same thing happens when you set the default.


> f = Foo('a')
> f.addData(1)
> f.addData(2)
> 
> f2 = Foo('b', [])

And in this case, you've passed a DIFFERENT empty list as an argument.


The normal Python way for handling this situation is to not use mutable
objects as defaults unless you want this behaviour. Instead, use None as
the default value:

class Foo:
    def __init__(self, name, data=None):
        self.name = name
        if data is None: self.data = []
        else: self.data = data


> Any ideas?  is this a bug?

Well, it's a bug in your code :)

It isn't a bug in Python. At worst, it is a "gotcha", but it is a
deliberate design decision, and quite useful. For example, this is good
for caching complicated calculations:

def function(x, _cache={}):
    # _cache is initialised to an empty dictionary at compile time
    if _cache.has_key(x):
        return _cache[x]
    else:
        # complicated and time consuming calculation happens
        _cache[x] = result
        return result




-- 
Steven.




More information about the Python-list mailing list