user1061147
user1061147

Reputation: 59

Can a python singleton class be inherited?

My idea is any one of the objects should exist for all the subclasses of a Singleton class. The code that I have been trying and the result matrix is given below. The matrix seems to be working fine in the case of subclasses. Am I going the wrong way? Did it get what happens in the case of a Parent class object and a subclass object?

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     |
'''

Upvotes: 5

Views: 12456

Answers (3)

Michael Hoffman
Michael Hoffman

Reputation: 34334

None of the subclasses' __new__() methods have an explicit return statement, so they all return None. That's why their new instances are all the same. With this code, they'll be the same as Singleton() too:

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)

It's not even necessary to define __new__() for the subclasses:

class A(Singleton):
    pass

class B(Singleton):
    pass

class C(B):
    pass

Upvotes: 5

Crampus
Crampus

Reputation: 491

I solve this problem with help of abstract classes. In my it looks like:

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

Lets check

>>> a1 = SecondLevelChild1()
>>> a2 = SecondLevelChild1()
>>> b1 = SecondLevelChild2()
>>> b2 = SecondLevelChild2()
>>> a1 == b1
False
>>> a1 ==a2
True
>>> b1 == b2
True
>>> 

ATTENTION! This solution will help if You need to instantiate only last level child classes. You would not able to instantiate abstract classes.

Upvotes: 0

Raymond Hettinger
Raymond Hettinger

Reputation: 226336

The code looks fine but it doesn't make sense to pick one singleton value to be shared for a class and its subclasses. The whole point of a subclass is to be different in some way from the parent class and from sibling subclasses. It seems odd to me that each class doesn't have its own distinct singleton instance.

Upvotes: 4

Related Questions