SourBitter SourBitter - 11 days ago 5
Python Question

Python list at module level

I broke down my problem to the following example program

xy8_block = [
{'pulse': {}},
]

class Dummy:
def __init__(self, block=list(xy8_block)):
self._block = block


dumdum = Dummy()
dumdum._block[0]['pulse']['test'] = 0
print(xy8_block)


If I run the program, the variable
xy8_block

is changed, although both variables
dumdum._block
and
xy8_block
have both a different memory address.

How can I avoid this problem without directly initialising
the class with the value.

Thanks in advance.

Answer

Instead of:

def __init__(self, block=list(xy8_block)):

Do:

from copy import deepcopy
def __init__(self, block=deepcopy(xy8_block)):

When you do list(my_list), you do a shallow copy of your list, which means its elements are still copied by reference.

In other words, as you correctly mentioned, xy8_block and dumdum._block do have different memory addresses. However, if you check memory addresses for xy8_block[0] and dumdum._block[0], you will see that they are the same.

By using deepcopy, you copy the list and its elements' values, not their references.

EDIT

As wisely noted by @FMc, this will still make all instances' _block attributes to point to the same object, since the list that results from deepcopy is created in the method's definition, not in its execution. So here's my suggestion:

from copy import deepcopy

class Dummy:
    def __init__(self, block=None):
        self._block = block or deepcopy(xy8_block)
Comments