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

Best way to partially deep copy a dictionary in Python?

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

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

我想做的事情很简短:我想任意更改字典,然后将其恢复为更改前的原始值。

我可以对此图进行一系列转换,但我没有任何可能的方法来事先知道我想进行哪种转换。转换将始终:

由于我不知道要进行哪种转换,所以我想对同一个图执行所有转换,然后选择一个。

一个明显的习语可以是:

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

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

我可以尝试为 Node class 重新定义 deepcopy,这 可行 ,但它非常老套,我 do 需要使用 deepcopy 来执行我的转换 t

以下是一个最小的工作示例,它可以完成我想要它做的事情——但是以一种我不想的方式,因为那时我需要创建一个解决方法让 deepcopy 在我需要的时候真正起作用。此外,执行转换的代码全部使用 gg 中的实际 Nodes,因为它现在是这样,所以不必更改太多会很好。

有更好的方法吗? (所有 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 级深度”副本。替换为:

dict_class_copy = deepcopy(dict_class)

有了这个:

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

你的测试通过了。