I am defining a singleton class, and using that class as a metaclass to create new classes.
class Singleton(type):
_lock: Lock = Lock()
_instance = {}
def __call__(cls, *args, **kwargs):
with cls._lock:
if cls not in cls._instance:
_instance = super().__call__(*args, **kwargs)
cls._instance[cls] = cls
return cls._instance.get(cls)
and the new class is defined like below
class SomeClass(metaclass=Singleton):
def __init__(self, some_list = []):
self.some_list = some_list
def add_to_list(self, a):
self.some_list.append(a)
some_class = SomeClass()
I am not able to access some_list variable of some_class object. It throws invalid attribute error.
some_class.some_list
a_list = [1,2,4,5]
for l in a_list:
some_class.add_to_list(l)
Also, I am not able to call add_to_list fn. It throws missing paramter "a" in the arguments.
Can some one help what I am missing in understanding of metaclass concept.
Your error is here:
cls._instance[cls] = cls
It should be:
cls._instance[cls] = _instance
You are storing the class itself on your class registry, not its single instance.
Before we proceed, I will point another problem your code:
def __init__(self, some_list = []):
Don't ever put a mutable object (an empty list) as a default parameter for a function or method: every time that function is called, the same object is re-used. In this case, this would be mitigated due to the method being in a singleton class, so this __init__
should run only once, but this is wrong enough. The correct pattern is:
def __init__(self, some_list = None):
if some_list is None:
some_list = []
This ensures a new, different, list is created each time the method is executed.
And, another thing, I don't know why this recipe of metaclass to create a singleton got so popular, but it is definitely overkill - I talk about it in some other answers, including Create singleton class in python by taking advantage of meta class , Dill doesn't seem to respect metaclass and Accessing the parameters of a constructor from a metaclass .