我试图理解如何用Python创建一个单例类。下面是我如何尝试的
class Singleton(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_)
return class_._instance
class MyClass(Singleton):
num_of_instances = 0
def __init__(self, real = 5, imaginary = 6):
self.real = real
self.imaginary = imaginary
MyClass.num_of_instances += 1
a = MyClass(10, 20)
print(a.real)
print(a.imaginary)
b = MyClass()
print(MyClass.num_of_instances) # 2
理想情况下,__new__()
使用对象实例调用__init__()
,但是在上面的情况下,当我尝试创建第二个对象b
时,不会调用__new__
,因为MyClass
的实例已经存在,那么为什么print语句printing num_of_instances
print 2
?你知道吗
对于每个
MyClass(...)
调用,都调用__new__
。如果没有调用它,它将无法返回singleton实例。你知道吗当
__new__
方法返回一个对象,并且该对象是传递给__new__
(或子类)的cls
参数的实例时,也会调用__init__
方法。你知道吗因此,对于每个
MyClass(...)
调用,__new__
被调用。__new__
方法总是返回当前类的实例,因此每次都会调用__init__
。在这里,每次都是同一个实例并不重要。你知道吗从^{} method documentation :
如果在方法中添加一些
print()
调用,则可以看到这种情况:您无法阻止自动
__init__
调用,至少在不重写其他内容的情况下是这样。如果您想避免每次调用__init__
,您有一些选择:不必对子类使用
__init__
方法。您可以发明自己的机制,__new__
可以寻找__singleton_init__
方法并调用:或者您的
__init__
方法可以检查是否已经在vars(self)
(或self.__dict__
)中设置了属性,只是不再设置属性:__new__
和__init__
逻辑在type.__call__
中实现;您可以创建一个metaclass来覆盖该逻辑。虽然您可以只调用__new__
(并保持一切不变),但让元类负责处理单例模式是有意义的:然后不要将其用作基类,而是与
metaclass=...
一起使用。如果更简单,可以创建空基类:上面的代码将在类上调用
__new__
,在结果实例上可选地后跟__init__
,只需一次。SingletonMeta.__call__
实现将永远返回singleton实例,而无需进一步调用:相关问题 更多 >
编程相关推荐