如何理解此代码:
我正在研究Python的Singleton实现:
class Singleton(object):
''''' A python style singleton '''
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
org = super(Singleton, cls) # what does this line mean, what's the funciton of it?
cls._instance = org.__new__(cls, *args, **kw) # and this line
return cls._instance
if __name__ == '__main__':
class SingleSpam(Singleton):
def __init__(self, s):
self.s = s
def __str__(self):
return self.s
s1 = SingleSpam('spam')
print id(s1), s1
s2 = SingleSpam('spa')
print id(s2), s2
print id(s1), s1
我不明白这两行代码:
org = super(Singleton, cls)
cls._instance = org.__new__(cls, *args, **kw)
cls
是否等于self
?org = super(Singleton, cls)
是什么意思? org.__new__(cls, *args, **kw)
创建Singleton实例的属性_instance
?答案 0 :(得分:0)
cls
是否等于self
?
不,__new__
是一种静态方法(自动,不需要@staticmethod
装饰器),不需要使用self
。这样做很好,因为没有self
可以通过它-__new__
的全部要点是 create 创建self
并返回它。 1
因此,它的第一个参数cls
是Python希望创建的对象类型。在这里,将是Singleton
。
尤其是在编写此代码时:
obj = Singleton()
…Python将其转换为以下内容(略为简化):
obj = Singleton.__new__(Singleton)
if isinstance(obj, Singleton):
obj.__init__()
org = super(Singleton, cls)
是什么意思?
super
的作用是:
返回将方法调用委托给类型的父级或同级类的代理对象。这对于访问已在类中重写的继承方法很有用。搜索顺序与
getattr()
使用的搜索顺序相同,只是类型本身被跳过。
换句话说,super(Singleton, cls)
是一个与cls
相似的对象(记住,它是Singleton
),只是当您尝试在其上调用方法时,它会跳过方法在Singleton
中定义,并且仅以方法解析顺序查找在下一个类中定义的方法-在这种情况下为object
。
为什么使用
org.__new__(cls, *args, **kw)
创建Singleton实例的属性_instance
?
请记住cls
是Singleton
,并且org
是超级代理对象,它引用与cls
相同的类对象,但是具有{{1 }},而不是object
的方法。 2
因此,当您调用Singleton
时,它不再调用org.__new__
代码并陷入无限循环,而是调用Singleton.__new__
代码。但是我们将其传递为object.__new__
(即cls
)作为参数。因此,我们要求Singleton
类型创建一个object
类型的新对象。这样,结果就是一个Singleton
实例,我们Singleton
。
但是首先,我们将其存储为return
(即cls._instance
),因此,下次我们尝试创建Singleton._instance
时,我们可以只返回相同的Singleton
如果我们只想要一个没有任何作用的cls._instance
类,那可能会更简单一些。但是Singleton
可以被子类化,并且其每个子类都将是一个单例类。从此开始:
Singleton
因此,它将调用class SingleSub(Singleton):
pass
obj = SingleSub()
。由于SingleSub.__new__(SingleSub)
不会覆盖SingleSub
,因此会调用__new__
,因此,在该代码中,Singleton.__new__(SingleSub)
现在是cls
而不是SingleSub
。
您应该能够从那里追踪事物,并查看Singleton
最终如何以单个SingleSub
结束,这与_instance
(及其{{1 }}恰好在您期望的时间被调用,依此类推。
1。当然,除非您正在编写扩展模块(例如,用于CPython的C模块),否则无法创建Singleton
。这就是为什么将它委派给__init__
的原因-最终它会变成self
或其他一些内置/扩展类型,确实知道如何创建实例。当然,您可以修改在链上传递的参数或在链上传递的super
。
2。在幕后,这与方法本身的工作方式非常相似,如果您已经知道方法的工作原理,这应该会使事情变得更加清楚,但是如果不知道,它可能比启蒙方法更令人困惑,因此请不要担心关于它。但是在某些时候,您应该完成Descriptor HOWTO。这很难,但是一旦您有了这个主意,Python中的所有“魔术”就会变得清晰起来。