2015-04-07 2 views
0

Я пытаюсь воспроизвести поведение 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').

Почему такое поведение происходит? Как я могу это предотвратить?

ответ

3

Проблема заключается в том, что любой список короче двух элементов является специальным обсаженным в вашей ReplicateIterable функции, поэтому новые объекты не создается в следующих случаях:

>>> l1 = [[], [0], [1, 2]] 
>>> l2 = ReplicateIterable(l1) 
>>> [i1 is i2 for i1, i2 in zip(l1, l2)] 
[True, True, False] 

Ваши комментарии в вопросе предполагают, что это было попытка избежать проблем с рекурсией со строками, но это не подходит для этого. Вместо этого, в частности, специальные строчки: