2015-11-12 5 views
0

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

def history(function, toAdd): 
    global history1 
    global history2 
    global history3 
    global history4 
    global history5 

    if function == 'add': 
     history5 = history4[:] 
     history4 = history3[:] 
     history3 = history2[:] 
     history2 = history1[:] 
     history1 = toAdd[:] 
    elif function == 'undo': 
     toReturn = history1[:] 
     history1 = history2[:] 
     history2 = history3[:] 
     history3 = history4[:] 
     history4 = history5[:] 
     return(toReturn[:]) 
    elif function == 'return': 
     return(history1[:]) 

Однако по какой-то причине список, что я перехожу к истории,

history('add', lst[:]) 

Еще связывает переменные, то есть, когда я что-то изменить в LST, я также изменить history1. Я также попытался использовать list() вместо [:], но это дает те же результаты. Что мне здесь не хватает?

+1

Добро пожаловать в SO! Сделайте минимальные примеры и скажите на своем названии * как * он не ведет себя так, как ожидалось. :-) –

+2

Вы знаете, что вы можете использовать один список для своего подхода вместо 5 переменных? Они поддерживают 'append (item)' и 'pop()'. –

ответ

1

Что вам не хватает, так это то, что lst[:] является только мелкой копией. Новый список, возвращаемый , может содержать и добавлять элементы без изменения исходного списка , но ссылки, содержащиеся в списке, по-прежнему доступны. Так что изменение элемента, скажем original_list[1].fooBar(), повлияет как на ссылку , содержащуюся в первоначальном списке и в новом списке, так как они являются одинаковыми ссылка.

Вы должны смотреть на использование deepcopy() (см copy modules's Python docs) - однако, что приходят с это собственный набор вопросов (объекты, которые не поддерживают его, копирование слишком много, и т.д.).

В вашем случае это, вероятно, означает, что history('add', lst[:]) действительно должно быть что-то вроде: history('add', copy.deepcopy(lst)).

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

def history(function, toAdd): 
    global history1 
    global history2 
    global history3 
    global history4 
    global history5 

    if function == 'add': 
     history5 = history4 
     history4 = history3 
     history3 = history2 
     history2 = history1 
     history1 = copy.deepcopy(toAdd) 
    elif function == 'undo': 
     toReturn = history1 
     history1 = history2 
     history2 = history3 
     history3 = history4 
     history4 = history5 

     # Should history5 still be valid at this point? Maybe do? 
     # history5 = None 

     # There could be several issues here. Remember, this is a deep copy 
     # of a previous object/collection. If your code is expecting the 
     # original object, you will not have it. 
     return toReturn 
    elif function == 'return': 
     # Is it expected that whomever calls this will receive a copy that 
     # they can manipulate? If so, the deepcopy() here is required. 
     return copy.deepcopy(history1) 

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

from collections import deque 
_history_store = deque(maxlen=5) 

def history(function, toAdd): 
    global _history_store 

    if function == 'add': 
     _history_store.append(copy.deepcopy(toAdd)) 

    elif function == 'undo': 
     if _history_store: 
      return _history_store.pop() 

     # No history to return. 
     return None 

    elif function == 'return': 
     if _history_store: 
      return copy.deepcopy(_history_store[-1]) 

     # No history to return. 
     return None 

Использование Deque поможет сохранить колпачок размера на 5 записей, без необходимости делать всех перетасовки себя.

 Смежные вопросы

  • Нет связанных вопросов^_^