Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Singleton different behavior when using class and dict to store the instance

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
like image 894
Victor Wong Avatar asked Mar 04 '26 23:03

Victor Wong


1 Answers

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.

like image 97
bb1 Avatar answered Mar 06 '26 13:03

bb1



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!