views:

145

answers:

2

Hello,

Have a look a this simple example. I don't quite understand why o1 prints "Hello Alex" twice. I would think that because of the default self.a is always reset to the empty list. Could someone explain to me what's the rationale here? Thank you so much.

class A(object):
        def __init__(self, a=[]):
            self.a = a

o = A()
o.a.append('Hello')
o.a.append('Alex')
print ' '.join(o.a)

# >> prints Hello Alex

o1 = A()
o1.a.append('Hello')
o1.a.append('Alex')
print ' '.join(o1.a)

# >> prints Hello Alex Hello Alex
+12  A: 

Read this Pitfall about mutable default function arguments: http://www.ferg.org/projects/python_gotchas.html

In short, when you define

def __init__(self,a=[])

The list referenced by self.a by default is defined only once, at definition-time, not run-time. So each time you call o.a.append or o1.a.append, you are modifying the same list.

The typical way to fix this is to say:

class A(object):
    def __init__(self, a=None):
        self.a = [] if a is None else a

By moving self.a=[] into the body of the __init__ function, a new empty list is created at run-time (each time __init__ is called), not at definition-time.

unutbu
Fix it like this: `class A(Object): def __init__(self, a = None): self.a = a if a is not None else []`
badp
Thanks, bp, :-)
unutbu
+6  A: 

Default arguments in Python, like:

def blah(a="default value")

are evaluated once and re-used in every call, so when you modify a you modify a globally. A possible solution is to do:

def blah(a=None):
  if a is None
    a = []

You can read more about this issue on: http://www.ferg.org/projects/python_gotchas.html#contents_item_6

Basically, never use mutable objects, like lists or dictionaries on a default value for an argument.

J. Pablo Fernández