2012-05-31 2 views
0

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

>>> seq = [1,[2,[3]]] 
>>> print arb_reverse(seq) 
[[[3],2],1] 
>>> seq = [9,[[],[0,1,[[],[2,[[],3]]]],[],[[[4],5]]]] 
>>> print arb_reverse(seq) 
[[[[5,[4]]],[],[[[[3,[]],2],[]],1,0],[]],9] 

Я придумал рекурсивного решение, которое хорошо работает:

def arb_reverse(seq): 
    result = [] 
    for element in reversed(seq): 
     if not is_list(element): 
      result.append(element) 
     else: 
      result.append(arb_reverse(element)) 
    return result 

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

def arb_reverse(seq): 
    elements = list(seq) #so input is not mutated, also tried seq[:] just to be thorough 
    result = [] 
    while elements: 
     item = elements.pop() 
     if isinstance(item, list): 
      item.reverse() #this operation seems to be the culprit 
      elements += item 
     else: 
      result.append(item) 
    return result 

Это возвращает сплюснутый полу обращенного списка (несколько ожидаемых), но интересная часть это то, что он делает на вход (не ожидали) ...

>>> a = [1, [2, [3]]] 
>>> arb_reverse(a) 
[2, 3, 1] 
>>> a 
[1, [[3], 2]] 
>>> p = [1, [2, 3, [4, [5, 6]]]] 
>>> print arb_reverse(p) 
[2, 3, 4, 5, 6, 1] 
>>> print p 
[1, [[[6, 5], 4], 3, 2]] 

У меня создалось впечатление, что, передав значения, содержащиеся во вводе, переменной, используя list() или input[:], как я это сделал с elements, я бы избегал мутирования ввода. Однако несколько заявлений на печать позже показали, что обратный метод имел руку в изменении исходного списка. Почему это?

ответ

3

Звонок list() делает новый список с неполноценными списками из оригинала.

Попробуйте (украдено из here):

from copy import deepcopy 
listB = deepcopy(listA) 
+0

Я предполагаю, что var = input [:] делает то же самое? Итак, хотя новый список создан, он все еще ссылается на исходные значения, которые заполняют список? –

+1

Вы правы. –

+0

Не нужно импортировать внешний модуль, я думаю, мне придется перебирать исходный список и убедиться, что все значения скопированы каким-то образом? –

2

Попробуйте запустить следующий код с помощью этого инструмента http://people.csail.mit.edu/pgbovine/python/tutor.html

o1 = [1, 2, 3] 
o2 = [4, 5, 6] 

l1 = [o1, o2] 

l2 = list(l1) 

l2[0].reverse() 

print l2 
print l1 

В частности посмотреть на то, что происходит, когда l2[0].reverse() называется.

Вы увидите, что при вызове list(), чтобы создать копию списка, списки по-прежнему ссылаются на одни и те же объекты.

+0

Не сделав этого еще, я предполагаю, что скопированный список все еще ссылается на объекты, заполняющие исходный список? –

+1

Точно, это всего лишь мелкая копия списка, она не дублирует объекты, содержащиеся в списке. – Acorn

+0

Учитывая необходимость отдельной функции для создания истинной копии, на какой длине входной рекурсии имеет смысл в отношении итерации в отношении решения? –