使用元类的Singleton类

时间:2017-05-26 10:05:52

标签: 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
        return cls._instances[cls]


class MyClass(metaclass=Singleton):
    pass

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

我的问题是为什么我们需要再次使用类型类的调用函数来初始化类?为什么我们不能像正常的类初始化那样调用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)

无论如何,这已进入无限循环。

1 个答案:

答案 0 :(得分:0)

因为尝试通过像在行cls._instances[cls] = cls(*args, **kwargs)中那样调用它来创建一个类的实例只是调用元类__call__,这是您尝试调用的确切方法,{ {3}}

现在,如果有一件事,你不应该只是为了创建单例而使用元类。

Python中的Metaclass机制很复杂 - 你在这个问题上遇到的问题表明你现在正在掌握如何简单的继承和对超类的方法的调用 - 而且元类比一个数量级更复杂。这一点。

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

如何创建单例类:

但是对于单身人士来说,你可以把所有的支票放在普通的__new__类方法中。不需要使用元类 - 只是普通的类继承:

_instances = {}

class Singleton(object):

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

      return _instances[cls]

只需从这一个继承你的单身人士课程。