2

I've read a bunch of useful information on SO as well as the article at http://www.phyast.pitt.edu/~micheles/python/metatype.html

However, I think I still did not find the answer. Hence a new question.

I'm creating a library of functions/classes for in-house use. As part of that I would like to create a Singleton class. Any other class should be able to inherit it and become Singleton. These classes should be sub-classable.

Per SO post at Creating a singleton in Python, I implemented:

class _Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(
                _Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class Singleton(_Singleton('SingletonMeta', (object,), {})):
    pass

It works. It helps create a singleton class that can be sub-classed.

There would be some classes in my library that would implement an abstract class using abc. Such class or a class implementing this abstract class can likely be Singleton.

So,

import abc
class Foo(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def bar(self): pass

class Bar(Singleton, Foo):    # This generates the meta-class conflict
    def bar(self):
        return 'implemented'
    def bat(self):
        return 'something else'

I am looking for inputs/help to help implement such a scenario.

**

Summary Requirements:

**

  • A mechanism to create a Singleton class.
  • A class implemented as Singleton (via the above mechanism) should be sub-classable. The sub- class my have additional/new methods than the base class.
  • A mechanism to create an abstract class (abc helps with this).
  • An implementation of this abstract class that acts as a Singleton. It
    may have additional methods than the abstract class itself.

Any inputs/help/pointers will be appreciated.

Regards

Sharad

Community
  • 1
  • 1
Sharad
  • 9,282
  • 3
  • 19
  • 36
  • If you think the requirements are conflicting, please let me know with your thoughts on why you think so. That'll be highly appreciated. – Sharad Aug 23 '16 at 07:54

1 Answers1

0

Instead of resorting to a metaclass to register your singletons, you can do that on the Base class for your hierarchy - just put the singleton logic on the __new__ method instead. That way, you don't have to change the metaclass just due to this aditional behaviors, and abc.metaclasses will just work.

import abc
class Foo(metaclass=abc.ABCMeta):
    _singleton_registry = {}
    def __new__(cls, *args, **kw):
        if cls in in __class__._singleton_registry:
            return __class__._singleton_registry[cls]
        singleton = super().__new__(*args, **kw)
        __class__._singleton_registry[cls] = singleton
        return singleton

    @abc.abstractmethod
    def bar(self): pass
jsbueno
  • 99,910
  • 10
  • 151
  • 209