0

I just started learning Python and come from a Java/C++ background and find the following behavior a little confusing. After calling s.add_trick("Woof") and d.add_trick("Woof"), s.tricks and d.tricks both contain ["Woof", "Bark"]. However, calling party() doesn't have the same behavior. Can someone explain?

class PartyAnimal:
    x = 0
    name = ''
    tricks = []

    def __init__(self, name):
        self.name = name

    def party(self):
        self.x += 1

    def add_trick(self, trick):
        self.tricks.append(trick)

s = PartyAnimal("Sally")
d = PartyAnimal("Danny")

s.party()
d.party()
s.add_trick("Woof")
d.add_trick("Bark")

print 's', s.name, s.x, s.tricks
print 'd', d.name, d.x, d.tricks

Output is this:

s Sally 1 ['Woof', 'Bark']
d Danny 1 ['Woof', 'Bark']
dawg
  • 98,345
  • 23
  • 131
  • 206
Danny Liu
  • 499
  • 2
  • 5
  • 12
  • `tricks` is a class instance so there is only one copy shared by every instance of `PartyAnimal()`. – dawg Mar 11 '16 at 18:48
  • In `C++` your variables `x`, `name` and `tricks` would be `static` i.e. there are shared by all instances of your class. To make them specific to an instance of your class, assign them to `self` only. – Cory Kramer Mar 11 '16 at 18:50
  • 1
    This is covered in the dupe target, but an important difference is that `self.tricks.append(trick)` modifies the existing `tricks` class attribute, but `self.x += 1` does _not_ modify the `x` class attribute because you're performing an assignment. Instead, it creates an `x` instance attribute (which shadows the class attribute of the same name) to hold the new integer object. – PM 2Ring Mar 11 '16 at 19:22
  • 1
    (cont) If you did `self.tricks = self.tricks + [trick]` that would also create a `tricks` instance attribute, although using `+=` wouldn't, it'd just mutate the class attribute, like the `.append` method does. `+=` on an integer _can't_ mutate the integer because Python integers are immutable. – PM 2Ring Mar 11 '16 at 19:22

1 Answers1

5

You're creating one tricks list that is shared by all instances of class. Create a new list in the __init__ instead:

def __init__(self, name):
    self.name = name
    self.tricks = []