在我的代码中,我正在尝试使用copy.deepcopy
复制一个类的实例。问题是在某些情况下出现以下错误是错误的:
TypeError: 'object.__new__(NotImplementedType) is not safe, use NotImplementedType.__new__()'
经过多次挖掘后,我发现我能够使用以下代码重现错误:
import copy
copy.deepcopy(__builtins__)
问题似乎是在某些时候它试图复制NotImplementedType
内置版。问题是为什么这样做?我没有在课堂上覆盖__deepcopy__
并且它不会一直发生。有没有人有任何关于追踪制作此类副本的请求来自哪里的提示?
我在copy
模块本身放了一些调试代码,以确保这就是正在发生的事情,但问题发生的地方到目前为止,在递归堆栈中很难做到很多我看到了。
答案 0 :(得分:3)
最后,我在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,发现其他人使用了相同的API,没有任何麻烦。如果它将来发生变化,我会接受命中。
我也知道这不是线程安全的(如果一个线程需要旧的行为,而我在另一个线程上复制我会被搞砸)但是现在再次对我来说不是问题。 / p>
希望在某些时候帮助其他人。
答案 1 :(得分:1)
你可以覆盖__deepcopy__方法:(python documentation)
为了让类定义自己的副本实现,它可以定义特殊方法 __ copy __()和 __ deepcopy __()。前者被称为实现浅拷贝操作;没有传递其他参数。调用后者来实现深拷贝操作;它传递了一个参数,即备忘录字典。如果 __ deepcopy __()实现需要制作组件的深层副本,它应该调用 deepcopy()函数,并将组件作为第一个参数,将备注字典作为第二个参数参数。
否则,您可以将模块保存在全局列表或其他内容中。
答案 2 :(得分:1)
您可以使用复制模块支持的pickle protocol来覆盖包含指向模块的指针的类的deepcopy行为,如here所述。特别是,您可以为该类定义__getstate__
和__setstate__
。 E.g:
>>> 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_module