2

Possible Duplicate:
“Least Astonishment” in Python: The Mutable Default Argument

I'm finding that dictionary arguments to the init() function of my class are defaulting to values I've previously set in previous instances. I really don't understand this behavior, and it doesn't seem to happen with lists or basic variables. Example code:

class TestClass:
  def __init__(
    self,
    adir={},
    alist=[],
    avar=None
  ):
    print("input adir: " + str(adir)) #for test2, shows test1.mydir
    self.mydir = adir
    self.mylist = alist
    self.myvar = avar

test1 = TestClass()   
test1.mydir['a'] = 'A'
test1.mylist = ['foo'] 
test1.myvar = 5

test2 = TestClass()
print(test2.mydir) #has same value of test1!
print(test2.mylist)
print(test2.myvar)

The output looks like this: initializing test1 input adir: {} initializing test2 input adir: {'a': 'A'} {'a': 'A'} [] None Why does the dictionary argument (adir) to test2 get set to test1.mydir? Especially, why is the behaviour different than other mutable types like list?

Thank you!

Community
  • 1
  • 1
Caleb
  • 3,839
  • 7
  • 26
  • 35
  • The only reason that `mydir` behaves differently than `mylist` is that you set an *element* of `test1.mydir` but you replace `test1.mylist`. Otherwise this is the mutable default argument issue again. – DSM Jul 03 '12 at 19:31

1 Answers1

2

As DSM says, don't modify mutable default arguments. Do this instead:

class TestClass:

  def __init__(self, adir=None, alist=None, avar=None):
    if alist is None:
      alist = []
    if adir is None:
      adir = {}
James Youngman
  • 3,623
  • 2
  • 19
  • 21
  • 1
    +infinity. (*ahem* - almost) Always use `None` for defaults – inspectorG4dget Jul 03 '12 at 19:35
  • 1
    Thanks a lot, I never realized this problem before... Now that I know the problem, I did a bit of googling. For posterity, [this article](http://effbot.org/zone/default-values.htm) isn't a bad discussion of what's going on here. – Caleb Jul 03 '12 at 20:34
  • and same issue for instance variable... use self.alist = {} is alist is None else alist – comte Jul 28 '20 at 11:27