我找到了创建单例类的最流行的方法之一,使用 _instance 和重写 __new__ 方法。这是:
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
但是当我尝试以这种方式使用它时,它表现得很奇怪:
class Child(Singleton):
def __init__(self):
self.a = random.randint(10, 1000)
x = Child()
y = Child()
print(x.__dict__) # {'a': 74}
print(y.__dict__) # {'a': 74} - not weird
print(Child().__dict__) # {'a': 222} - weird (for me)
有人可以解释为什么会发生吗?
PS:我使用的是python 3.10
为了创建一个对象,Python 首先在其类上调用
__new__
,然后在该对象上调用 __init__
。
当您“创建”
Child
的实例时,Python将调用Singleton.__new__
,然后调用Child.__init__
。但是 Singleton.__new__
总是返回同一个对象 _instance
,因此 Child.__init__
总是会重新初始化同一个对象。
x
和 y
包含相同的对象,因为所有 Child
都是相同的对象。这就是为什么 x.__dict__
和 y.__dict__
是相同的。但是当你第三次调用 Child
时,它会重新初始化该对象,更改其字典。 print(Child().__dict__)
给出不同的值,因为它在打印之前调用 Child
。
并不是第三次调用
Child
会产生不同的对象;而是会产生不同的对象。相反,对象本身发生了变化。
如果您以这种方式实现单例,则不应使用
__init__
,因为每次调用 Child
时都会调用它并重新初始化对象。如果您需要初始化单例的值,您可以在 if 语句中的 __new__
中执行此操作,以便初始化仅完成一次。
还要考虑为什么需要创建单例的子类。一个单例应该只有一个成员,所以如果有任何
Child
的实例,那么所有 Singleton
一定都是 Child
,所以 Singleton
和 Child
最好合并到一节课。