Python 使用元类的单例类

Python 使用元类的单例类,python,singleton,Python,Singleton,下面是创建单例元类的著名代码: class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) cls.x = 5 r

下面是创建单例元类的著名代码:

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


class MyClass(metaclass=Singleton):
    pass

m = MyClass()
v = MyClass()
print (m.x)
m.x = 420
print (v.x)
我的问题是为什么我们需要再次使用class类型的call函数来初始化类?为什么我们不能像普通的类初始化那样调用init方法来实现呢。大概是这样的:

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


class MyClass(metaclass=Singleton):
    pass

m = MyClass()
v = MyClass()
print (m.x)
m.x = 420
print (v.x)

无论如何,这将进入一个无限循环。

因为尝试创建一个类的实例时,只需像在
cls行中那样调用它。{u instances[cls]=cls(*args,**kwargs)
只需自己调用元类
\u call\uu
,这正是您尝试调用的方法

现在,如果有一件事,您不应该仅仅为了创建单例而使用元类

Python中的元类机制是复杂的——您在这个问题上遇到的问题表明您现在已经掌握了如何在超类上进行简单的继承和方法调用——而元类要比这复杂一个数量级

而且,除了复杂之外,具有自定义元类的类通常不能与具有自定义元类的其他类组合,因此一般规则是将它们的使用保持在最低限度

如何创建单例类: 但是对于creatign-a-singleton,您可以将所有检查放在类普通
\uuuu-new\uuu
方法中。无需使用元类进行feedle-只需简单的类继承:

_instances = {}

class Singleton(object):

   def __new__(cls, *args, **kw):
      if not cls in _instances:
          instance = super().__new__(cls)
          _instances[cls] = instance

      return _instances[cls]
然后从这个继承你的单例类