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']
4
  • tricks is a class instance so there is only one copy shared by every instance of PartyAnimal(). Commented Mar 11, 2016 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. Commented Mar 11, 2016 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. Commented Mar 11, 2016 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. Commented Mar 11, 2016 at 19:22

1 Answer 1

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 = []
Sign up to request clarification or add additional context in comments.

14 Comments

@shahkalpesh No because that is semantically different than having each instance have its own list. Putting the list at the class level would be like making it static in C style languages.
it is totally OK if it is supposed to be a class variable, akin to static member variable in Java/C#
@DannyLiu because you're not mutating that integer or string, you're setting the x or name attribute to point to another object instead.
@shahkalpesh never too much reputation to start reading Python 3 tutorials
@AnttiHaapala got it. Coming from c# background, I thought self in python is this in c#/java. Hence, you can't do this to refer to a class level variable (static in c#/java). Thank you. I learned something new today.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.