0

I have the following Python (3.6.0) class:

class SampleClass(object):
    @staticmethod
    def create(*data):
        sample_instance = SampleClass()
        sample_instance.add_data(*data)
        return sample_instance

    def __init__(self, data_map={}):
        super(SampleClass, self).__init__()
        self.data_map = data_map

    def add_data(self, *data):
        for key, value in data:
            self.data_map.setdefault(key, []).append(value)

Where the static method create is a convenience method for initializing a new instance. However, when invoking create multiple times, the data_map property is not recreated. For example:

sample_instance1 = SampleClass.create(('a', 1), ('b', 2), ('c', 3))
sample_instance2 = SampleClass.create()
sample_instance1.data_map == sample_instance2.data_map  # True
sample_instance1.data_map is sample_instance2.data_map  # True

If I change the __init__ method to this, the issue goes away:

    def __init__(self):
        super(SampleClass, self).__init__()
        self.data_map = {}

Could someone help me understand what's going on here?

treyhakanson
  • 4,611
  • 2
  • 16
  • 33

1 Answers1

1

The default argument data_map={} is only created once when the function is defined. If you mutate it, the changes will persist through future invocations. That means that every instance of the SampleClass that isn't given a new dict has a self.data_map that is pointing to the same (default) dict instance.

gilch
  • 10,813
  • 1
  • 23
  • 28
  • Brilliant, thank you; what's the best way to recreate each time while still taking in the kwarg? Something like `__init__(self, data_map=None)` and then `self.data_map = data_map or {}`? – treyhakanson Jul 21 '18 at 22:34
  • 1
    @treyhakanson yes, that's a good approach. This question has been marked as a duplicate, see the answers in the linked question for other approaches. – gilch Jul 21 '18 at 22:45