【发布时间】:2014-06-18 05:45:22
【问题描述】:
在this question 中,Anthony Hatchkins 给出了基于 Python 回退到的字典复制代码的 deepcopy 的默认实现:
def __deepcopy__(self, memo):
cls = self.__class__
result = cls.__new__(cls)
memo[id(self)] = result
for k, v in self.__dict__.items():
setattr(result, k, deepcopy(v, memo))
return result
我想要一个基于 pickling 和 unpickling 的默认实现,Python 在退回到 dict-copying 之前会选择它。
这是我的尝试,但没有成功:
def __deepcopy__(self, memo):
new, args, state = self.__reduce__()
result = new(*args)
if state:
result.__setstate__(state)
memo[id(self)] = result
return result
一旦我有了这样的方法,我就可以制作一个版本,其中包含有关复制内容和复制方式的附加选项。
reduce 和 setstate 的存在由一个基类保证:
@staticmethod
def kwargs_new(cls, new_kwargs, *new_args):
"""
Override this method to use a different new.
"""
retval = cls.__new__(cls, *new_args, **new_kwargs)
retval.__init__(*new_args, **new_kwargs)
return retval
"""
Define default getstate and setstate for use in coöperative inheritance.
"""
def __getstate__(self):
return {}
def __setstate__(self, state):
self.__dict__.update(state)
def __getnewargs_ex__(self):
return ((), {})
def __reduce__(self):
"""
Reimplement __reduce__ so that it calls __getnewargs_ex__
regardless of the Python version.
It will pass the keyword arguments to object.__new__.
It also exposes a kwargs_new static method that can be overridden for
use by __reduce__.
"""
new_args, new_kwargs = self.__getnewargs_ex__()
state = self.__getstate__()
return (type(self).kwargs_new,
(type(self), new_kwargs,) + tuple(new_args),
state)
【问题讨论】:
-
为什么需要基于泡菜的解决方案?我没有看到优势。此外,让 pickler 备忘录和 deepcopy 备忘录很好地协同工作可能是一个问题。
-
@user2357112:因为那时我可以免费获得酸洗。我可以使用相同的代码来实现“保存”和“加载”。
-
您可以通过实施 pickle 协议免费获得深度复制,例如通过覆盖
__getstate__和__setstate__。 This question 可能是相关的。 -
@shx2:是的,这就是我最终所做的。基类还是需要上面的代码来处理getnewargs_ex等
标签: python python-3.x pickle deep-copy