在我的代码中,我尝试使用copy.deepcopy复制一个类的实例。问题是,在某些情况下,它会出错,出现以下错误:
TypeError: 'object.__new__(NotImplementedType) is not safe, use NotImplementedType.__new__()'在深入研究之后,我发现我可以使用以下代码重现错误:
import copy
copy.deepcopy(__builtins__) 问题似乎是在某个时候,它试图复制NotImplementedType内置代码。问题是,它为什么要这样做?我没有在我的类中重写__deepcopy__,而且它也不是一直都会发生。有没有人有什么建议来追踪这种类型的复制请求是从哪里来的?
我已经在copy模块本身中放入了一些调试代码,以确保这是正在发生的事情,但是问题发生的地方在递归堆栈的下面,所以很难理解我所看到的东西。
发布于 2009-12-22 18:13:21
最后,我深入研究了copy源代码,并提出了以下解决方案:
from copy import deepcopy, _deepcopy_dispatch
from types import ModuleType
class MyType(object):
def __init__(self):
self.module = __builtins__
def copy(self):
''' Patch the deepcopy dispatcher to pass modules back unchanged '''
_deepcopy_dispatch[ModuleType] = lambda x, m: x
result = deepcopy(self)
del _deepcopy_dispatch[ModuleType]
return result
MyType().copy()我意识到这使用了私有API,但我找不到另一种干净的方法来实现同样的事情。我在网上做了一个quick search,发现其他人也在使用同样的应用程序接口,没有任何麻烦。如果将来有变化,我会接受打击的。
我也意识到这不是线程安全的(如果一个线程需要旧的行为,而我正在复制另一个线程,我就完蛋了),但这对我来说现在也不是问题。
希望这能在某一时刻帮助其他人。
发布于 2009-12-22 07:59:43
您可以重写__deepcopy__方法:(python documentation)
为了让类定义自己的复制实现,它可以定义特殊的方法__copy__()和__deepcopy__().前者被调用来实现浅层复制操作;不传递额外的参数。后者被调用来实现深度复制操作;它被传递给一个参数,即memo字典。如果__deepcopy__()实现需要创建一个组件的深度副本,它应该调用deepcopy()函数,并将该组件作为第一个参数,并将备忘录字典作为第二个参数。
否则,您可以将模块保存在全局列表或其他文件中。
发布于 2009-12-24 02:18:19
如here所述,您可以通过使用复制模块所支持的pickle protocol来覆盖包含指向模块的指针的类的深度复制行为。特别是,您可以为该类定义__getstate__和__setstate__。例如:
>>> class MyClass:
... def __getstate__(self):
... state = self.__dict__.copy()
... del state['some_module']
... return state
... def __setstate__(self, state):
... self.__dict__.update(state)
... self.some_module = some_modulehttps://stackoverflow.com/questions/1941887
复制相似问题