Python单例类可以被继承吗?

5 投票
3 回答
11173 浏览
提问于 2025-04-17 06:53

我的想法是,任何一个对象都应该在所有单例类的子类中存在。下面是我尝试的代码和结果矩阵。这个矩阵在子类的情况下似乎运行得很好。我是不是走错了方向?在父类对象和子类对象的情况下,这个情况是怎样的呢?

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

撰写回答