循环依赖性对于
deepcopy
当你:
-
-
建设
,而不仅仅是
初始化
问题是取消勾选对象(
深度复制
默认情况下,通过pickle和unpickle复制自定义对象,除非特殊
__deepcopy__
方法)在不初始化的情况下创建空对象,然后尝试逐个填充其属性。当它试图填补
node1
的属性,它需要初始化
node2
节点1
(在这两种情况下,由于
edge_dict
边缘dict
一个人
Node
节点
它增加了
没有它的
id
属性尚未设置,因此对其进行哈希的尝试失败。
__new__
确保在初始化可变(可能是递归)属性和定义
pickle
帮手
__getnewargs__
(或
__getnewargs_ex__
)使其正确使用。具体来说,将类定义更改为:
class Node:
# __new__ instead of __init__ to establish necessary id invariant
# You could use both __new__ and __init__, but that's usually more complicated
# than you really need
def __new__(cls, p_id):
self = super().__new__(cls) # Must explicitly create the new object
# Aside from explicit construction and return, rest of __new__
# is same as __init__
self.id = p_id
self.edge_dict = {}
self.degree = 0
return self # __new__ returns the new object
def __getnewargs__(self):
# Return the arguments that *must* be passed to __new__
return (self.id,)
# ... rest of class is unchanged ...
object
和改变
super()
super(Node, cls)
在里面
__新建__
; 给出的代码是更简单的Python 3代码。
只有
copy.deepcopy
__新建__
/
(需要新样式的类)将仅覆盖深度复制。您需要在原始类上定义以下额外方法(并确保模块导入
copy
),否则将其保持不变:
def __deepcopy__(self, memo):
# Deepcopy only the id attribute, then construct the new instance and map
# the id() of the existing copy to the new instance in the memo dictionary
memo[id(self)] = newself = self.__class__(copy.deepcopy(self.id, memo))
# Now that memo is populated with a hashable instance, copy the other attributes:
newself.degree = copy.deepcopy(self.degree, memo)
# Safe to deepcopy edge_dict now, because backreferences to self will
# be remapped to newself automatically
newself.edge_dict = copy.deepcopy(self.edge_dict, memo)
return newself