0

I stepped into a feature of python very dangerous to my style of programming. I wondered what pattern would be best to resolve these conflicts. The follwoing example should give a good insight

class TestObject():

    def __init__(self, dt = {}):
        self.dt = dt

    def update_dt(self, new_dt):
        for k, v in new_dt.items():
            self.dt[k] = v


def main():
    first = {'a': 1}

    d1 = TestObject()
    print(TestObject().__dict__)

    d1.update_dt(first)
    print(TestObject().__dict__)

To my surprise the last print statement returned {'dt': {'a': 1}} and not {}. While I was baffled at first, I think I now understand what happens. By 'updating' the self.dt I am not only changing the attribute of object d1 but also the parameter dtof the class.

My solution would be to never specify the default parameter as a list, dict or similar (unless this feature is wanted) and always use None instead, i.e.

def __init__(self, dt = None):
    if dt is None:
        dt = {}

    self.dt = dt

But is there a more elegant way to tackle this 'problem'?

quantguy
  • 237
  • 2
  • 10
  • Do you mean, `if dt is not None`? – Jacobr365 Apr 24 '17 at 13:22
  • 1
    That's about the way to do it: have a look at [Why are default values shared between objects?](https://docs.python.org/3/faq/programming.html#why-are-default-values-shared-between-objects) of the Python's FAQs. – Pier Paolo Apr 24 '17 at 13:29
  • http://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – Chris_Rands Apr 24 '17 at 13:30
  • Sorry this was an error @Jacobr365. I changed the post. Thank you – quantguy Apr 24 '17 at 13:38
  • Nope. There are no more elegant ways. None I've seen widely used in production anyway. So, the good news is that you're on the right track. The bad news is that the right track is not very pretty. – Noufal Ibrahim Apr 24 '17 at 13:39

1 Answers1

0

Your solution is correct. This behaviour occurs with any mutable object, such as lists for example. So you should always use None (or a non mutable object) as a default parameter.

https://docs.python.org/3.6/reference/datamodel.html