當有自定義的class繼承了dict時,在使用copy.deepcopy便需要重寫__deepcopy__方法,這個方法一不小心就會寫成shallow copy(只copy了最外層) 或是寫出死循環,如下反例:
def __deepcopy__(self, memo=None, _nil=[]):
dict = _MyDict()
for key in self.keys():
dict.__setattr__(key,self.__getattr__(key))
注意到參數中實際上有一個memodict,是可以用來避免死循環的,字典copy的主要過程首先是這樣:
for key in self.keys():
dict .__setattr__(deepcopy(key, memo),
deepcopy(self.__getattr__(key), memo))
key和value都需要調用各自的deepcopy方法,之後在函數入口處應當首先判斷當前對象是否在memo中出現過(這裡寫法參照deepcopy函數源碼),即,是否是遞歸的循環調用, 如果沒有,需要將自己的id加到字典中,表明自己正在進行deep copy:
def __deepcopy__(self, memo=None, _nil=[]):
dict = _MyDict()
for key in self.keys():
dict.__setattr__(key,self.__getattr__(key))
整體代碼如下:
class _MyDict(dict):
....
def __deepcopy__(self, memo=None, _nil=[]):
if memo is None:
memo = {
}
d = id(self)
y = memo.get(d, _nil)
if y is not _nil:
return y
dict = _MyDict()
memo[d] = id(dict)
for key in self.keys():
dict .__setattr__(deepcopy(key, memo),
deepcopy(self.__getattr__(key), memo))
return dict