python - deepcopy的第二个参数memo的作用是什么?

标签 python

from copy import* 
a=[1,2,3,4]
c={'a':'aaa'}
print c
#{'a': 'aaa'}
b=deepcopy(a,c)
print b

print c
# print {'a': 'aaa', 10310992: 3, 10310980: 4, 10311016: 1, 11588784: [1, 2, 3, 4, [1, 2, 3, 4]], 11566456: [1, 2, 3, 4], 10311004: 2}

为什么要打印那个

请尽量使用代码,而不是文字,因为我的英文不是很好,谢谢

在 django.utils.tree.py 中

def __deepcopy__(self, memodict):
        """
        Utility method used by copy.deepcopy().
        """
        obj = Node(connector=self.connector, negated=self.negated)
        obj.__class__ = self.__class__
        obj.children = deepcopy(self.children, memodict)
        obj.subtree_parents = deepcopy(self.subtree_parents, memodict)
        return obj



import copy
memo = {}
x1 = range(5)
x2=range(6,9)
x3=[2,3,4,11]
y1 = copy.deepcopy(x1, memo)
y2=copy.deepcopy(x2, memo)
y3=copy.deepcopy(x3,memo)
print memo
print id(y1),id(y2),id(y3)
y1[0]='www'
print y1,y2,y3
print memo

打印:

{10310992: 3, 10310980: 4, 10311016: 1, 11588784: [0, 1, 2, 3, 4, [0, 1, 2, 3, 4]], 10311028: 0, 11566456: [0, 1, 2, 3, 4], 10311004: 2}
{11572448: [6, 7, 8], 10310992: 3, 10310980: 4, 10311016: 1, 11572368: [2, 3, 4, 11], 10310956: 6, 10310896: 11, 10310944: 7, 11588784: [0, 1, 2, 3, 4, [0, 1, 2, 3, 4], 6, 7, 8, [6, 7, 8], 11, [2, 3, 4, 11]], 10311028: 0, 11566456: [0, 1, 2, 3, 4], 10310932: 8, 10311004: 2}
11572408 11581280 11580960
['www', 1, 2, 3, 4] [6, 7, 8] [2, 3, 4, 11]
{11572448: [6, 7, 8], 10310992: 3, 10310980: 4, 10311016: 1, 11572368: [2, 3, 4, 11], 10310956: 6, 10310896: 11, 10310944: 7, 11588784: [0, 1, 2, 3, 4, [0, 1, 2, 3, 4], 6, 7, 8, [6, 7, 8], 11, [2, 3, 4, 11]], 10311028: 0, 11566456: ['www', 1, 2, 3, 4], 10310932: 8, 10311004: 2}

最佳答案

上面没有人给出一个很好的例子来说明如何使用它。

这是我的做法:

def __deepcopy__(self, memo):
    copy = type(self)()
    memo[id(self)] = copy
    copy._member1 = self._member1
    copy._member2 = deepcopy(self._member2, memo)
    return copy

member1 是不需要深度复制的对象(如字符串或整数),而 member2 是需要深度复制的对象,如另一种自定义类型或列表或字典。

我已经在高度纠结的对象图上使用了上面的代码并且效果很好。

如果你还想让你的类 pickleable(用于文件保存/加载),getstate/setstate 没有类似的 memo 参数,换句话说 pickle系统会以某种方式跟踪已引用的对象,因此您无需担心。

以上适用于您继承自的 PyQt5 类(以及 pickling - 例如我可以深度复制或 pickle 自定义 QMainWindow、QWidget、QGraphicsItem 等)

如果您的构造函数中有一些创建新对象的初始化代码,例如创建新 CustomScene(QGraphicsScene) 的 CustomWidget(QWidget),但是您想将场景从一个 CustomWidget 腌制或复制到一个新的一个,然后一种方法是在你的 __init__ 中创建一个 new=True 参数并说:

def __init__(..., new=True):
    ....
    if new:
       self._scene = CustomScene()

def __deepcopy__(self, memo):
    copy = type(self)(..., new=False)
    ....
    copy._scene = deepcopy(self._scene, memo)
    ....

这确保您不会创建 CustomScene(或一些进行大量初始化的大类)两次!您还应该在 __setstate__ 方法中使用相同的设置 (new=False),例如:

 def __setstate__(self, data):
     self.__init__(...., new=False)
     self._member1 = data['member 1']
     .....

还有其他方法可以解决上述问题,但这是我总结并经常使用的方法。

为什么我也谈到酸洗?因为通常在任何应用程序中您都需要这两者,并且您同时维护它们。如果您将成员添加到您的类中,您会将其添加到 setstate、getstate、 deepcopy 代码中。我会制定一条规则,对于您创建的任何新类,如果您计划在您的应用程序中复制/粘贴文件保存/加载,则创建上述三种方法。替代方案是 JSON 并自己保存/加载,但是您还有很多工作要做,包括内存。

因此,要支持以上所有内容,您需要 __deepcopy__、__setstate__ 和 __getstate__ 方法并导入 deepcopy:

from copy import deepcopy

,当你编写你的 pickle loader/saver 函数时(你调用 pickle.load()/pickle.dump() 来加载/保存你的对象层次结构/图表)做 import _pickle as pickle 以获得最佳速度(_pickle 是一些更快的 C impl,通常与您的应用要求兼容)。

关于python - deepcopy的第二个参数memo的作用是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1950563/

相关文章:

python - 在 nginx 上运行 django 时提供测试页面

python - 使用 xml.dom.minidom 解析 xml 时出现内存泄漏

python - 如何检查 twisted.internet.protocol 实例是否已断开连接

python - 检测 postgresql 数据库中子网重叠的最佳方法

Python 线程 - 让线程开始而不等待前一个线程完成

python - 编程新手并试图完成学校的这项任务,我似乎无法将列表中的数字添加在一起

python - Apache Spark - ModuleNotFoundError : No module named 'mysql'

python - 字典值的部分和

python - 在 python 2 和 3 的 spyder 之间切换

Python 从列表名称而不是列表项返回字符