deepcopy不尊重元类

2024-09-30 20:23:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个类,按照设计,必须遵循singleton模式。所以我继续使用元类来实现它。所有的工作都很顺利,直到报告了一个bug,总之,我的singleton类的deepcopy-ied实例不是同一个实例。在

我可以通过继承一个basesingleton类型的类来解决这个问题,但是我不希望这样,因为this question中指出的原因。在

这一问题的工作实例如下:

class SingletonMeta(type):
    def __init__(cls, name, bases, dict):
        super(SingletonMeta, cls).__init__(name, bases, dict)
        cls.instance = None 
    def __call__(cls,*args,**kw):
        print "SingletonMeta __call__ was called"
        if cls.instance is None:
            cls.instance = super(SingletonMeta, cls).__call__(*args, **kw)
        return cls.instance

class MyClass1(object):
    __metaclass__ = SingletonMeta

class SingletonBase(object):
    _instance = None
    def __new__(class_, *args, **kwargs):
        print "SingletonBase __new__ was called"
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyClass2(SingletonBase):
  pass

from copy import deepcopy as dcp

mm1 = MyClass1()
mm2 = dcp(mm1)
print "mm1 is mm2:", mm1 is mm2

mb1 = MyClass2()
mb2 = dcp(mb1)
print "mb1 is mb2:", mb1 is mb2

输出:

^{pr2}$

你能告诉我该如何解决这个问题吗?我运行的是python2.7.X


Tags: 实例instancenoneobjectisdefargscall
2条回答

copy模块上的文档这样说:

In order for a class to define its own copy implementation, it can define special methods __copy__() and __deepcopy__(). [...] The latter is called to implement the deep copy operation; it is passed one argument, the memo dictionary. [...]

因此,如果您声明这些返回self,那么应该可以实现这个目的。在

当您需要自定义类创建(而不是实例创建)时,可以在元类的__new__方法中进行:

def __new__(cls, name, bases, dict):
    dict['__deepcopy__'] = dict['__copy__'] = lambda self, *args: self
    return super(SingletonMeta, cls).__new__(cls, name, bases, dict)

你的测试会

^{pr2}$

您还需要定义__copy__,甚至浅拷贝也会产生新的实例。在

很高兴我在那条线索上的解决方案派上了用场。在

相关问题 更多 >