Why do these two base classes result in the child objects having different behavior?
class Base:
_instance: "Base" = None
def __new__(cls) -> "Base":
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
class A(Base):
def foo(self):
return "foo"
class B(Base):
def quz(self):
return "quz"
a = A()
b = B()
print(id(a))
print(id(b))
140035075937792
140035075948400
On the other hand
from typing import Dict
class Base:
_instances: Dict[int, "Base"] = {}
def __new__(cls) -> "Base":
if 0 not in cls._instances:
cls._instances[0] = super().__new__(cls)
return cls._instances[0]
class A(Base):
def foo(self):
return "foo"
class B(Base):
def quz(self):
return "quz"
a = A()
b = B()
print(id(a))
print(id(b))
140035075947296
140035075947296
When a = A() is executed, the __new__ method is called with the class A as its argument. This sets the value of the class attribute A._instance. Likewise, b = B() sets the value of B._instance.
In the first case, the original value of Base._instance, A.instance and B._instance is None, which is a non-mutable object, so changing this value in A or B does not affect the other two classes.
In the second case, A._instance, B._instance and Base._instance point to the same dictionary. Since a dictionary is a mutable object, modifying this dictionary via one class affect all three classes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With