0

I have a class:

class Tree(object):

    def __init__(self):
        self.health = 100

And I use it here:

tree_list += [Tree()] * random.randint(4, 12)

This makes the list contain multiple Tree() classes. The problem is that when I change 'health' in one of the items in tree_list:

tree_list[0].health -= 25

It changes the 'health' value in EVERY item in tree_list. Can someone please help me figure out why it changes the value for every item instead of the item I intend to change? Any help would be appreciated. :D

  • 6
    "*This makes the list contain multiple Tree() classes.*" No, it makes a list of multiple *objects*, not classes. Except it only creates a single object, then puts it in the list multiple times. All list elements refer to the same object. – melpomene Jul 07 '18 at 03:07
  • Thanks for explaining it, I didn't even realise it did that. – Aiden Blishen Cuneo Jul 07 '18 at 03:08
  • 1
    This is also covered [in the official Python FAQ](https://docs.python.org/3/faq/programming.html#why-did-changing-list-y-also-change-list-x). Meanwhile, the best answer on SO is to a question that isn't _exactly_ the same as yours, so please let us know if it actually answers your question, or if we should add another link that isn't so list-specific. – abarnert Jul 07 '18 at 03:17

1 Answers1

0

I solved it by changing this:

tree_list += [Tree()] * random.randint(4, 12)

To this:

for a in range(random.randint(4, 12)):
    tree_list.append(Tree())

Probably not the best way to do it, but it works now.

  • 1
    It's a fine way to do it. – juanpa.arrivillaga Jul 07 '18 at 03:16
  • 1
    There's nothing wrong with your solution. The most idiomatic way to do this is probably with a list comprehension: `tree_list = [Tree() for _ in random.randint(4, 12)]`. But your code has the same effect (in fact, it's just a more explicit way to write exactly the same operations), so if it's easier for you to understand/maintain, do it that way. – abarnert Jul 07 '18 at 03:19