在 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} }
我想做的事情很简短:我想任意更改字典,然后将其恢复为更改前的原始值。
我可以对此图进行一系列转换,但我没有任何可能的方法来事先知道我想进行哪种转换。转换将始终:
- 删除一键
- 添加两个新顶点
- 改变大约 1/n 条边
由于我不知道要进行哪种转换,所以我想对同一个图执行所有转换,然后选择一个。
一个明显的习语可以是:
- 将词典复制到临时词典(
temp = g
)
- 对每个转换重复
t
:
- 对图
g
进行变换t
,形成图g'
- 记下有关图表的信息
g'
以备后用
- 设置
g = temp
以将图形恢复到已知良好状态
这不起作用,因为复制字典只执行浅表复制,所以对 g
的所有更改也会在 temp
上执行。
我可以使用 deepcopy
,但即使这样也无法正常工作。我想deepcopy
实际的字典g
,但是g
(Nodes
)的值中的键和元素不能被深度复制,因为在我的转换中,我会查找 g
中但不在 temp
中的元素,因为它们现在是新对象。
我可以尝试为 Node
class 重新定义 deepcopy
,这 可行 ,但它非常老套,我 do 需要使用 deepcopy 来执行我的转换 t
。
以下是一个最小的工作示例,它可以完成我想要它做的事情——但是以一种我不想的方式,因为那时我需要创建一个解决方法让 deepcopy 在我需要的时候真正起作用。此外,执行转换的代码全部使用 g
和 g
中的实际 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()}
你的测试通过了。
我有一个表示为 dict
的图表,其中每个键都是(自定义)Node
class 的实例,值是实例集Nodes
。所以,基本上,图表看起来像这样,但更大:
g = { Node1 : {Node2, Node3}, Node2 : {Node4}, Node3: set(), Node4 : {Node1} }
我想做的事情很简短:我想任意更改字典,然后将其恢复为更改前的原始值。
我可以对此图进行一系列转换,但我没有任何可能的方法来事先知道我想进行哪种转换。转换将始终:
- 删除一键
- 添加两个新顶点
- 改变大约 1/n 条边
由于我不知道要进行哪种转换,所以我想对同一个图执行所有转换,然后选择一个。
一个明显的习语可以是:
- 将词典复制到临时词典(
temp = g
) - 对每个转换重复
t
:- 对图
g
进行变换t
,形成图g'
- 记下有关图表的信息
g'
以备后用 - 设置
g = temp
以将图形恢复到已知良好状态
- 对图
这不起作用,因为复制字典只执行浅表复制,所以对 g
的所有更改也会在 temp
上执行。
我可以使用 deepcopy
,但即使这样也无法正常工作。我想deepcopy
实际的字典g
,但是g
(Nodes
)的值中的键和元素不能被深度复制,因为在我的转换中,我会查找 g
中但不在 temp
中的元素,因为它们现在是新对象。
我可以尝试为 Node
class 重新定义 deepcopy
,这 可行 ,但它非常老套,我 do 需要使用 deepcopy 来执行我的转换 t
。
以下是一个最小的工作示例,它可以完成我想要它做的事情——但是以一种我不想的方式,因为那时我需要创建一个解决方法让 deepcopy 在我需要的时候真正起作用。此外,执行转换的代码全部使用 g
和 g
中的实际 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()}
你的测试通过了。