我试图复制copy.deepcopy
的行为。我有一种方法有一些非常奇怪的行为。
def ReplicateIterable(i):
try:
if len(i) > 1:
return [ReplicateIterable(e) for e in i]
else:
return i
except TypeError:
return i
这是我的功能。 try
块用于捕获非迭代。我得到了一些无限的递归问题,因为字符串是可迭代的,我使用字符作为我的列表的元素,因此它在递归之前检查可迭代长度是否为>1
。
我在测试用例中得到了这种行为:
>>> State = [['a', 'b', 'b', 'b', 'c', 'c', 'c'], []]
>>> TempState = ReplicateIterable(State)
>>> TempState
[['a', 'b', 'b', 'b', 'c', 'c', 'c'], []]
>>> TempState[0].remove('c')
>>> TempState[1].append('c')
>>> State
[['a', 'b', 'b', 'b', 'c', 'c', 'c'], ['c']]
>>> TempState
[['a', 'b', 'b', 'b', 'c', 'c'], ['c']]
显然,TempState[0]
指向State[0]
,但TempState[1]
> 指向State[1]
。 State[0]
操作保持TempState[0].remove('c')
不变,但State[1]
修改了TempState[1]
和TempState[1].append('c')
。
为什么会出现这种情况?我该如何预防?
答案 0 :(得分:3)
问题在于,ReplicateIterable
函数中任何短于两个项目的列表都是特殊的,因此在这些情况下不会创建新对象:
>>> l1 = [[], [0], [1, 2]]
>>> l2 = ReplicateIterable(l1)
>>> [i1 is i2 for i1, i2 in zip(l1, l2)]
[True, True, False]
您在问题中的评论表明这是为了避免使用字符串的递归问题,但这并不是一种合适的方法。相反,特别是特殊情况字符串:
def replicate_iterable(iter): # note style guide compliance
"""Deep copy the iterable."""
if isinstance(iter, str):
return iter
try:
return [replicate_iterable(item) for item in iter]
except TypeError:
return iter