我正在学习如何在Python中创建单身人士(请不要说明为什么单身人士不好或者这样,这里不是主题)
基于一个实现,我尝试这样做:
class Singleton(object):
def __init__(self, klass):
print "S init"
self.klass = klass
self.instance = None
def __call__(self, *args, **kwargs):
print "S call"
if self.instance is None:
self.instance = self.klass(*args, **kwargs)
else:
self.instance(*args, **kwargs)
return self.instance
@Singleton
class KlasseA:
def __new__(cls, *args, **kwargs):
print "KA new"
def __init__(self, s):
print "KA init"
self.__init2(s)
def __call__(self, s=None):
print "KA call"
self.__init2(s)
def __init2(self, s):
if s: self.s = s
@Singleton
class KlasseB:
def __new__(cls, *args, **kwargs):
print "KB new"
def __init__(self, s):
print "KB init"
self.__init2(s)
def __call__(self, s=None):
print "KB call"
self.__init2(s)
def __init2(self, s):
if s: self.s = s
现在,通过在同一.py文件中附加以下行来测试上述内容:
print ""
a = KlasseA('one')
print "a -> ", id(a), a.s
b = KlasseA('two')
print "b -> ", id(b), b.s
print "a -> ", id(a), a.s
c = KlasseA()
print "c -> ", id(c), c.s
print "b -> ", id(b), b.s
print "a -> ", id(a), a.s
d = KlasseB('three')
print "d -> ", id(d), d.s
print "a -> ", id(a), a.s
我得到了以下内容:
S init
S init
S call
KA init
a -> 140525844905496 one
S call
KA call
b -> 140525844905496 two
a -> 140525844905496 two
S call
KA call
c -> 140525844905496 two
b -> 140525844905496 two
a -> 140525844905496 two
S call
KB init
d -> 140525844905568 three
a -> 140525844905496 two
所以,单身装饰器确实有效。我在这里不明白的是:
我认为装饰器重新定义了通话,因此通话KlasseA()
实际上是对Singleton(KlasseA)()
的调用。不应该为每个Singleton
调用生成一个新的KlasseA()
实例吗?
我注意到有两个" S init"行,很可能是因为在Singleton()
和KlasseA
声明期间调用了KlasseB
。因此,创建了Singleton
的两个实例。这些实例保存在哪里?
是否有可能出现的问题'使用上面的Singleton装饰器配方?
答案 0 :(得分:1)
装饰器在定义类时应用,而不是在实例化时应用。关于你的观点1,它实际上相当于:
class KlasseA():
...
KlasseA = Singleton(KlasseA)
a = KlasseA()
关于第2点,名称KlasseA
和KlasseB
绑定到Singleton
的实例,如上所示。
关于第3点,我不确定仅因为您尝试创建新实例而调用类的单个实例的__call__
方法是有意义的。也就是说,我认为Singleton.__call__
应该只是
def __call__(self, *args, **kwargs):
if self.instance is None:
self.instance = self.klass(*arg, **kwargs)
return self.instance