Truff2107
Truff2107

Reputation: 1

How to change a list attribute of an instance inside a list

I have some trouble with the following code:

from beat_class import Beat

# creates a list 'beats' and fills it with instances of the class 'Beat'
beats = []
for i in range(4):
    beats.append(Beat())

# prints out the list attribute 'tones' of each 'Beat'-instance
for i in beats:
    print(i.tones)
print()

# appends an int value to the first instance of the list 'beats'
beats[0].tones.append(3)

# prints out the 'tones'-attributes again
for i in beats:
    print(i.tones)  
print()

# compares the ids of the first 2 instances in the list 'beats' and prints
# 'True' if they are the same
print(id(beats[0].tones) == id(beats[1].tones))

Output:

[]
[]
[]
[]

[3]
[3]
[3]
[3]

True

The comments in the code above show what its different parts do.

My problem is that once I want to append a value to the list attribute tones of an instance of the class Beat inside the list beats, said attribute gets changed in all of the instances instead of just the one I wanted to.

Since I‘m relatively new to Python I‘m not quite sure how to fix this. I assume that this has something to do with the ids of the tones-attributes which appear to be all the same according to the console output of the last line of code above.

I have already tried out some stuff with the copy() and deepcopy()functions but none of it worked. :/

I would be really happy if someone could help me out. :)

Upvotes: 0

Views: 44

Answers (1)

Yevhen Kuzmovych
Yevhen Kuzmovych

Reputation: 12130

Does your Beats __init__ look something like:

class Beat:
   def __init__(self, tones=[]):
       self.tones = tones

If so, the problem is that tones defaults to the same list (actually the same list in memory). What you want is something like:

class Beat:
   def __init__(self, tones=None):
       self.tones = tones or []

That way you'll have a separate list for each Beat instance.

See more info on this here

Upvotes: 1

Related Questions