Say that I have the following Python code:
import sys
class DogStr:
tricks = ''
def add_trick(self, trick):
self.tricks = trick
class DogList:
tricks = []
def add_trick(self, trick):
self.tricks.append(trick)
# Dealing with DogStr
d = DogStr()
e = DogStr()
d.add_trick('trick d')
e.add_trick('trick e')
print(d.tricks)
print(e.tricks)
# Dealing with DogList
d = DogList()
e = DogList()
d.add_trick('trick d')
e.add_trick('trick e')
print(d.tricks)
print(e.tricks)
Running this code with Python 3.6.5, I get the following output:
trick d
trick e
['trick d', 'trick e']
['trick d', 'trick e']
The difference between DogStr and DogList is that I treat tricks
as a string on former and as a list on the latter.
When dealing with DogStr, tricks is behaving as an instance variable. BUT with DogList tricks is behaving as a class variable.
I was expecting to see the same behaviour on both calls, i.e.: if the two last lines of the output are identical, so should be the first two.
So I wonder. What is the explanation for that?
The difference is not int the type of the object, but in what your code does to it.
There is a big difference between these two:
self.tricks = trick
and:
self.tricks.append(trick)
The first one self.tricks = trick
assigns a value to attribute tricks
of self
.
The second one self.tricks.append(trick)
retrieves self.tricks
and calls a method on it (which here modifies its values).
The problem, in your case, is that there is no tricks
defined on self
instance, so self.tricks.append
gets the tricks
attribute of the class and modifies it, but self.tricks = ...
creates a new attribute on self
instead.
The fact that one of them is a string and the other is a list is not really relevant. It would be the same if both were lists. Note that they could not both be strings because strings are immutable and thus have no append method
This is wrong:
def add_trick(self, trick):
self.tricks = trick
If tricks
is a class attribute, add_trick
should be a class method:
@classmethod
def add_trick(cls, trick):
cls.tricks = trick
If there are reasons for add_trick
to be an instance method, then simply do this:
def add_trick(self, trick):
DogStr.tricks = trick