Python单例类可以被继承吗?
我的想法是,任何一个对象都应该在所有单例类的子类中存在。下面是我尝试的代码和结果矩阵。这个矩阵在子类的情况下似乎运行得很好。我是不是走错了方向?在父类对象和子类对象的情况下,这个情况是怎样的呢?
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(
cls, *args, **kwargs)
return cls._instance
class A(Singleton):
def __new__(cls, *args, **kwargs):
super(A, cls).__new__(cls, *args, **kwargs)
class B(Singleton):
def __new__(cls, *args, **kwargs):
super(B, cls).__new__(cls, *args, **kwargs)
class C(B):
def __new__(cls, *args, **kwargs):
super(B, cls).__new__(cls, *args, **kwargs)
if __name__ == '__main__':
s1=Singleton()
s2=Singleton()
if(id(s1)==id(s2)):
print "Same"
else:
print "Different"
'''
I got a result matrix for s1 and s2
|************ s2 **************************|
s1 |Singleton() |A() | B() | C() |
===========|==========================================|
Singleton()|Same |Different|Different|Different|
A() |Different |Same |Same |Same |
B() |Different |Same |Same |Same |
C() |Different |Same |Same |Same |
'''
3 个回答
0
我用抽象类来解决这个问题。在我这里,它看起来是这样的:
from abc import ABCMeta, abstractmethod
class BasicClass(object):
__metaclass__ = ABCMeta
instance = None
def __new__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = super(BasicClass, cls).__new__(
cls, *args, **kwargs)
return cls.instance
@abstractmethod
def action(self):
pass#do smthing
class FirstLevelChild(BasicClass):
__metaclass__ = ABCMeta
@abstractmethod
def action(self):
pass#do smthing in this or other abstract method
# also pearent method can be called with help of super
class SecondLevelChild1(FirstLevelChild):
def action(self):
pass#do smthing unique for this class
# in this or other abstract method
# also pearent method can be called with help of super
class SecondLevelChild2(FirstLevelChild):
def action(self):
pass#do smthing unique for this class
# in this or other abstract method
# also pearent method can be called with help of super
我们来检查一下
>>> a1 = SecondLevelChild1()
>>> a2 = SecondLevelChild1()
>>> b1 = SecondLevelChild2()
>>> b2 = SecondLevelChild2()
>>> a1 == b1
False
>>> a1 ==a2
True
>>> b1 == b2
True
>>>
注意!这个解决方案适用于你只需要创建最后一级子类的情况。你不能直接创建抽象类的实例。
3
这段代码看起来没问题,但让我觉得奇怪的是,为什么要让一个类和它的子类共享同一个单例值。子类的主要目的就是在某种程度上与父类和兄弟子类有所不同。如果每个类都没有自己独特的单例实例,那就显得有点不合理了。
4
这些子类的 __new__()
方法里没有明确的 return
语句,所以它们都会返回 None
。这就是为什么它们的新实例都是一样的原因。用这段代码,它们和 Singleton()
的实例也是一样的:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return cls._instance
class A(Singleton):
def __new__(cls, *args, **kwargs):
return super(A, cls).__new__(cls, *args, **kwargs)
class B(Singleton):
def __new__(cls, *args, **kwargs):
return super(B, cls).__new__(cls, *args, **kwargs)
class C(B):
def __new__(cls, *args, **kwargs):
return super(C, cls).__new__(cls, *args, **kwargs)
其实子类里根本不需要定义 __new__()
方法:
class A(Singleton):
pass
class B(Singleton):
pass
class C(B):
pass