gpt4 book ai didi

python - 需要澄清 "decorator class"在 Python 中如何工作

转载 作者:太空宇宙 更新时间:2023-11-03 18:05:49 24 4
gpt4 key购买 nike

我正在学习如何在 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

所以,单例装饰器确实有效。我在这里不明白的是:

  1. 我认为装饰器重新定义了调用,因此调用 KlasseA() 实际上是对 Singleton(KlasseA)() 的调用>。这难道不应该为每个 KlasseA() 调用生成一个新的 Singleton 实例吗?

  2. 我注意到有两行“S init”,很可能是因为在声明 KlasseAKlasseB< 期间调用了 Singleton()/。因此,创建了两个 Singleton 实例。这些实例保存在哪里?

  3. 上述 Singleton 装饰器配方是否存在可能的“陷阱”?

最佳答案

装饰器在定义类时应用,而不是在实例化类时应用。关于你的第1点,它实际上相当于:

class KlasseA():
...

KlasseA = Singleton(KlasseA)

a = KlasseA()

关于你的第2点,名字KlasseAKlasseB绑定(bind)到 Singleton 的实例,如上所示。

关于第 3 点,我不确定调用 __call__ 是否有意义。类的单个实例的方法只是因为您尝试创建一个新实例。也就是说,我认为Singleton.__call__应该只是

def __call__(self, *args, **kwargs):
if self.instance is None:
self.instance = self.klass(*arg, **kwargs)
return self.instance

关于python - 需要澄清 "decorator class"在 Python 中如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26922728/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com