4

在我的代码中,我尝试使用copy.deepcopy. 问题是在某些情况下它会出现以下错误:

TypeError: 'object.__new__(NotImplementedType) is not safe, use NotImplementedType.__new__()'

经过大量挖掘,我发现我能够使用以下代码重现错误:

import copy
copy.deepcopy(__builtins__) 

问题似乎是在某些时候它试图复制NotImplementedType内置。问题是它为什么要这样做?我在课堂上没有被覆盖__deepcopy__,也不是一直发生。有没有人有任何提示来追踪制作这种类型的副本的请求来自哪里?

我已经在copy模块本身中放置了一些调试代码,以确保这是正在发生的事情,但是问题发生的地方在递归堆栈中很远,很难理解我所看到的。

4

3 回答 3

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,但我找不到另一种实现相同目标的干净方法。我在网上进行了快速搜索,发现其他人使用相同的 API 没有任何麻烦。如果它在未来发生变化,我会接受打击。

我也知道这不是线程安全的(如果一个线程在我在另一个线程上复制时需要旧的行为,我会被搞砸),但现在对我来说再次不是问题。

希望在某些时候能帮助别人。

于 2009-12-22T10:13:20.883 回答
1

您可以使用复制模块支持的pickle 协议覆盖包含指向模块的指针的类的 deepcopy 行为,如此所述。特别是,您可以为该类定义__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_module
于 2009-12-23T18:18:18.577 回答
1

您可以覆盖 __deepcopy__ 方法:(python 文档

为了让一个类定义自己的复制实现,它可以定义特殊方法__copy__()__deepcopy__()。前者被调用来实现浅拷贝操作;没有传递额外的参数。后者被调用来实现深拷贝操作;它被传递一个参数,备忘录字典。如果__deepcopy__()实现需要对组件进行深层复制,它应该调用deepcopy()函数,将组件作为第一个参数,将备忘录字典作为第二个参数。

否则,您可以将模块保存在全局列表或其他内容中。

于 2009-12-21T23:59:42.607 回答