Python Class Vs Instance Properties

Python Class Vs Instance Properties

Reading Time: 3 minutes

Python is not always friendly for developers that come from languages like Java or C++ or SWIFT. The next topic got me debugging my code for a few hours, so I hope to save them for you. I wanted to create a class which its instances would have a list in each of them, for the sake of simplicity we will add only numbers to this list. So this is what I wrote:

class MyClass:
	
	inner_list=[]
	
	def __init__(self):
		pass
		
	def add(self, some):
		self.inner_list.append(some)

Then when I wanted to test it, something strange happens to me, my tests failed and I got weired results, something messed up with 2 instances I created.

a = MyClass()
b = MyClass()

Lets add some values to them:

a.add(1)
b.add(2)

The expected print of them would be:

print(a.inner_list) # expected [1]
print(a.inner_list) # expected [2]

But what we get is:

print(a.inner_list) # [1, 2]
print(a.inner_list) # [1, 2]

So what happened here? The explanation is very simple, properties that initialized in class scope and not inside the constructor (__init__) method and on self, are class properties, just like Java’s static variables, and because list is a mutable object the list is not only shared but referenced to the same list and its values.

If we would have declared immutable property such as number, the case would be a little different. Consider the following:

class MyClass:
	
	number=0
	inner_list=[]
	
	def __init__(self):
		pass
		
	def add(self, some):
		self.inner_list.append(some)

a = MyClass()
b = MyClass()
print(a.number) # prints 0
print(b.number) # prints 0
a.number = 1
print(a.number) # prints 1
print(b.number) # prints 0

Because number property is immutable, when you assign a.number (in contrast to append) you basically override (replacing it) with a new value.

The rewritten class is:

class MyClass:	
	def __init__(self):
		self.inner_list = []
		self.number= 0
	
	def add(self, some):
		self.inner_list.append(some)

Cheers,