Its an interesting thing what you are doing there, and its based on mutability:
The initial __shared_state
that you declared is created before any of your code is execute. That dictionary is known as Class Attribute, because it is linked to the class, not an instance (does not use self
for declaration). This means that __shared_state
is shared between b1
and b2
because it is created before them, and since it is a dict
, it is mutable.
What does it mean that it is mutable?
It means that one dictionary assigned to two different instances, will reference to same memory address, and even if we change the dicttonary, the memory address will remain the same. Here is a probe:
class Example:
__shared_state = {1: 1}
def __init__(self):
self.__dict__ = self.__shared_state
print(self.__shared_state)
ex1 = Example()
ex2 = Example()
print(id(ex1.__dict__), id(ex2.__dict__))
# Prints
# {1: 1}
# {1: 1}
# 140704387518944 140704387518944
Notice how they have the same id? That's because they are refering to the same object, and since the dictionary
type is mutable, altering the dictionary in one object, means that you are changing it for both, because they are the same:
# Executing this
ex1.val1 = 2
# Equals this
ex1.__dict__['val1'] = 2
# Which also equals this
Example.__shared_state['val1'] = 2
This does not happen with integers, which are immutable:
class Example:
__shared_state = 2
def __init__(self):
self.a = self.__shared_state
print(self.__shared_state)
ex1 = Example()
ex2 = Example()
ex2.a = 3
print(id(ex1.a), id(ex2.a))
# Prints
# 2
# 2
# 9302176 9302208
# Notice that once we change ex2.a, its ID changes!
When you delete your __shared_state
, the moment you assign b1.val1 = 'Jaga Gola!!!'
and b1.val2 = 'BOOOM!!!'
, it is only assigning to the dictionary from b1
, thats why when you try to print b2.val1
and b2.val2
it raises an Error.