3

我定义了这个单例元类:

class Singleton(type):
    """Metaclass which implements the singleton pattern"""

    _instances = {}

    def __call__(self, *args, **kwargs):
        if self not in self._instances:
            self._instances[self] = super(Singleton, self).__call__(*args, **kwargs)
        return self._instances[self]

现在,我想测试一切是否正常。这是我尝试过的:

  • 我创建了同一类的两个对象(具有Singleton元类的类)-它们的id()匹配项
  • 我创建了一个对象并将其分配给第二个变量——它们的id()匹配项
  • 我导入了copy模块并复制了第一个对象copy.copy()-它们id()现在不匹配

我想知道为什么复制对象的 id 与原始对象不匹配。既然是单例,这两个对象不应该有相同的id吗?

4

1 回答 1

5

copy模块不会创建新实例;相反,它创建一个空类,并__class__在该对象上重新分配以专门避免原始的__new__or__init__方法。

您需要提供一个自定义__copy__挂钩来返回未更改的实例:

class Singleton(type):
    """Metaclass which implements the singleton pattern"""

    _instances = {}

    def __call__(self, *args, **kwargs):
        if self not in self._instances:
            self._instances[self] = super(Singleton, self).__call__(*args, **kwargs)
        return self._instances[self]

    def __copy__(cls, instance):
        return instance

copy__copy__直接在类上查找方法;相反,它是在metaclass上找到的,在类上查找__copy__将返回一个绑定方法,并且copy(期望一个未绑定的方法)显式传入实例。这意味着将有两个参数传递给__copy__; 第一个是类(元类的实例),第二个是该类的实例(self在传统方法中)。

不幸的是,__deepcopy__改为在实例上查找,并且找不到元类方法。

于 2013-09-18T11:34:07.203 回答