0

I tried to write a class with mutable object as default value. I know for a single function we should set parameter as None and check the parameter in case the side effect for the function like following code. But I was wondering how about when I tried to initialize a class? side effect by using mutable object as a default value for a variable

def func(k, v, para = {}):
    para[k] = v
    return para
print(func('a', 1)) #expect {'a': 1}, actually return {'a': 1}
print(func('b', 2)) #expect {'a': 1}, actually return {'a': 1, 'b': 2}
print(func('c', 3)) #expect {'a': 1}, actually return {'a': 1, 'b': 2, 'c': 3}
#how about class?
class T
    def __init__(self, para = {})
    #or
    #def __init__(self, para = None)
        #para = para or dict()
        self.para = para
fdelafuente
  • 1,114
  • 1
  • 13
  • 24
jacobcan118
  • 7,797
  • 12
  • 50
  • 95

1 Answers1

3

Best practice is the following.

Source: Why is the empty dictionary a dangerous default value in Python?

def func(k, v, para=None):
    if para is None:
        para = dict()
    para[k] = v
    return para
print(func('a', 1)) #returns {'a': 1}
print(func('b', 2)) #returns {'b': 2}
print(func('c', 3)) #returns {'c': 3}

And yes, I'm pretty sure the same applies to classes.

class T:
    def __init__(self, para=None):
        if para is None:
            para = dict()
        self.para = para



Let's just test what happens with classes:

class T:
    def __init__(self, k, v, para={}):
        self.para = para
        self.para[k] = v

print(T('a',1).para) #returns {'a': 1}
print(T('b',2).para) #returns {'a': 1, 'b': 2}
print(T('c',3).para) #returns {'a': 1, 'b': 2, 'c': 3}

So yes, the same applies to class constructors.

Finomnis
  • 18,094
  • 1
  • 20
  • 27
  • 1
    I would suggest to explicitly test for `if para is None`. Because your test will create a new dict even if an empty one is passed, which might be surprising as the caller won't get the passed dict updated. – deets Jun 13 '19 at 15:05
  • Agree. Good catch. – Finomnis Jun 13 '19 at 15:08