simple OOP + Lists question

Hello again! I’m back with another silly little question:RocknRoll: as my struggle to learn Python continues.

My problem boils down to this:


class Test:
  num = 0
  list = [1,1,1,1]
  
  def __init__(self,a):
    self.num = a
  def increase(self):
    self.num +=1
  
  def manipulateList(self,pattern):
        dir = 0
        for item in pattern:
            if item == 1:
                self.list[dir] = 0
            dir += 1

I have a class with two attributes:
num
list

and two methods:
increase : adds 1 to num
manipulateList : takes a list as a parameter, what it does is pretty self explanatory.

Now, when I run the following code:


test1 = Test(0)
test2 = Test(test1.num)
test2.increase()
test2.increase()
test1.increase()
print(test1.num)
print(test2.num)

The result is ofcourse:


1
2

Which proves I’m manipulating two separate instances of the attribute.
Now the fun part:
When I run this code:


test1 = Test(0)
test2 = Test(test1.num)

#Print the attributes before manipulation
print (test2.list)
print (test1.list)

#Manipulate
test1.manipulateList([1,1,1,1])

#Print them after ONE has been changed
print (test2.list)
print (test1.list)

I get the following output:


[1, 1, 1, 1]
[1, 1, 1, 1]
[0, 0, 0, 0]
[0, 0, 0, 0]

Both objects’ lists have been changed?

Now what I don’t understand is:
a) WHY?!
b) How do I write a function that changes a list attribute of only one object, not all instances of the class?

Thanks in advance for any hints, and pardon if this is another REALLY n00b question :slight_smile:

first of all, you use two keywords as variable names: dir and list. This works, but i would suggest that you pick other names for your variables to avoid confusion.

The variables you have defined (list and num) are static class members, so they belong to the class itself, not the instances of it.
you should define them in your init method instead, like this:

def __init__(self, a):
    self.num = a
    self.list = [1,1,1,1]

A side note, regarding the weird behaviour:
If you really wanted to have static class members you should change them with

Test.num+=1

Otherwise you just end up with a local copy of the variable.

And why does the list behave different to the number then? That is because you don’t copy the list itself, you copy a reference to the list. So in practice you only ever have one copy of the list shared between both instances of the class.

I hope that my bad explanation was at least a bit understandable :slight_smile:
Just ask if something is unclear