在Python中部分深度复制字典的最佳方法?

时间:2016-03-03 23:09:52

标签: python dictionary copy deep-copy

我有一个表示为dict的图表,其中每个键都是(自定义的)Node类的实例,值是Nodes的实例集。所以,基本上,图表看起来像这样,但更大:

g = { Node1 : {Node2, Node3}, Node2 : {Node4}, Node3: set(), Node4 : {Node1} }

用我想要做的非常简短的话来说:我想随意更改字典,然后在更改之前将其恢复为原始值。

我可以对此图进行一系列转换,但我没有任何可能的方法事先知道我想要做哪些转换。转型总是:

  • 删除一个键
  • 添加两个新顶点
  • 改变1 / n边

由于我不知道我想要做哪个转换,因此我想对每个转换执行相同的图形,然后选择一个转换。

一个明显的习语可能是:

  • 将字典复制到临时字典(temp = g
  • 对每次转化重复t
    • 在图表t上执行转化g以形成图表g'
    • 记下有关图表g'以供日后使用
    • 的信息
    • 设置g = temp以将图表恢复为已知良好状态

这不起作用,因为复制字典只执行浅拷贝,因此g的所有更改也会在temp上执行。

我可以使用deepcopy,但即使这样也无法正常工作。我想deepcopy实际字典g,但gNodes)值中的键和元素无法进行深度复制,因为在我的转换中,我会查找g但不在temp中的元素,因为它们现在是新对象。

我可以尝试为deepcopy类重新定义Node,其中可以,但它非常hackish我需要使用deepcopy执行我的转换t

以下是一个最小的工作示例,它可以完成我想要它做的事情 - 但是我不想的方式因为那时我需要创建一个解决方法来使deepcopy实际工作时我需要它。此外,执行转换的代码全部使用gNodes中的实际g,因为它现在正好,因此不必更改大部分内容会很好。

有更好的方法吗? (所有print应为True

from copy import deepcopy

class MyClass:

    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return str(self.value)

    def __deepcopy__(self, memo):
    # do not rly deep copy plx
        return self

    class1 = MyClass(1)
    class2 = MyClass(2)
    class3 = MyClass(3)

    dict_class = { class1 : {class2, class3}, class2 : {class3}, class3 : {class1}}

    #### Want to create a copy of the dictionary with exact same objects... ####

    dict_class_copy = deepcopy(dict_class)

    print(dict_class)
    print(dict_class_copy)

    print(class1 in dict_class and class2 in dict_class and class3 in dict_class)
    print(class1 in dict_class_copy and class2 in dict_class_copy and class3 in dict_class_copy)

    dict_class.pop(class2)
    dict_class[class1].remove(class3)

    # don't want to change original dictionary key values
    print(class2 not in dict_class and class2 in dict_class_copy)

    # this breaks w/o deepcopy!
    print(class3 not in dict_class[class1] and class3 in dict_class_copy[class1])

    # reassign it back 
    dict_class = dict_class_copy 

    # i want this back!
    print(class2 in dict_class)
    print(class3 in dict_class[class1])

1 个答案:

答案 0 :(得分:1)

制作一个" 1级深度"通过复制密钥并制作集合的副本来复制字典。替换这个:

dict_class_copy = deepcopy(dict_class)

用这个:

dict_class_copy = {k:set(v) for k,v in dict_class.items()}

并且您的测试通过了。