How to break the link between lists in sibling objects?

Question:

I need to create a set of objects of the same class. The example code is:

class Model:
    name = ''
    my_values = []

models = []
for i in range(3):
    m = Model()
    m.name = str(i)
    m.my_values.append(i)
    models.append(m)

‘m.name = str(i)’ works perfect, but ‘m.my_values.append(i)’ does not: it appends all ‘i’ values to lists of all objects (and I need to add ‘0’ to the first object list, ‘1’ to the second and so long). How to break the ling between lists?

Asked By: Vlad

||

Answers:

You should create an __init__ function for your Model, because your my_values is an attribute and it’s shared across all instances of the class.

class Model:
    def __init__(self, name):
        self.name = name
        self.my_values = []


models = []
for i in range(3):
    m = Model(i)
    m.my_values.append(i)
    models.append(m)
Answered By: MisteryDush

What happened here is that you set a default value for my_value in Model, which will create a list at the start of the program. my_value won’t be re-initialize (create new list) for every new instance of class created and will continue to use the first one, which leads to the unwanted behavior you are observing. To fix this issue, initiate my_value inside __init__ function.

class Model:
    def __init__(self, name):
        self.name = name
        self.my_values = []


models = []
for i in range(3):
    m = Model(name=str(i))
    m.my_values.append(i)
    print(m.my_values)  # prints out [0], [1], [2] respectively
    models.append(m)

You can either use __init__ as suggested or create a dataclass (https://docs.python.org/3/library/dataclasses.html)

from dataclasses import dataclass, field                                                                                                     

@dataclass
class Model:
   values : list = field(default_factory=list)     # note you have to use field for mutables
Answered By: Axeltherabbit
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.