I was trying to implement singleton classes for my project and an interesting post in StackOverflow on the same
Creating a singleton in Python
I decided to go with the metaclasses approach mentioned..
Now.. I tried to add a method to get and clear the instances (in case the user wants to get rid of the current instance and create a new one..):
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]
    def getInstance(cls):
        print("Class is {}".format(cls.__name__))
        if not cls in cls._instances:
            raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
        return cls._instances[cls]
    def clearInstance(cls):
        cls._instances.pop(cls, None)
class someClass(metaclass=Singleton):
    def __init__(self,val):
        self.value = val
I am able to create objects successfully..
In [9]: sc = someClass(1)
In [10]: sc.value
Out[10]: 1
But when I do dir(someClass) the 2 methods are not displayed:
In [14]: dir(someClass)
Out[14]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']
Nevertheless I am able to call the methods..
In [13]: someClass.getInstance()
Class is someClass
Out[13]: <__main__.someClass at 0x7f728b180860>
In all the examples on metaclass I see online I see __new__, __init__ and __call__ methods implemented but I don't see any additional methods added. Is it correct to add methods to the metaclass?
I also tried a small variation of the above metaclass code:
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]
    @classmethod
    def getInstance(cls):
        print("Class is {}".format(cls.__name__))
        if not cls in cls._instances:
            raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
        return cls._instances[cls]
    @classmethod
    def clearInstance(cls):
        cls._instances.pop(cls, None)
Marked the 2 methods as class method..
Now when I attempt to call them:
In [2]: sc = someClass(1)
In [3]: someClass.getInstance()
Class is Singleton
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-3-c83fe01aa254> in <module>()
----> 1 someClass.getInstance()
<ipython-input-1-9efb6548d92d> in getInstance(cls)
     12
     13                 if not cls in cls._instances:
---> 14                         raise LookupError("No instance of the class {cls} create yet.".format(cls.__name__))
     15
     16                 return cls._instances[cls]
KeyError: 'cls'
As you can see the class is print says its Singleton when I decorate it as classmethod. Otherwise it shows the correct class. I don't understand this behavior, can someone explain?
 
     
     
     
     
    