Python 列出了不符合预期的行为
Python lists not behaving as intended
所以我最近一直在学习列表的可变属性,以及变量在 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() 而不是 [:],但结果相同。我在这里错过了什么?
你缺少的是 lst[:]
只是一个浅拷贝。新名单
返回的可以添加和删除元素而不影响原始元素
列表,但列表中包含的引用仍然是共享的。所以修改
一个元素,比如 original_list[1].fooBar()
,将同时影响引用
包含在原始列表和新列表中,因为它们 相同
参考。
您需要查看使用 deepcopy()
(请参阅 复制模块的 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
使用双端队列有助于将大小上限保持在 5 个条目,而无需执行
所有的洗牌自己。
所以我最近一直在学习列表的可变属性,以及变量在 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() 而不是 [:],但结果相同。我在这里错过了什么?
你缺少的是 lst[:]
只是一个浅拷贝。新名单
返回的可以添加和删除元素而不影响原始元素
列表,但列表中包含的引用仍然是共享的。所以修改
一个元素,比如 original_list[1].fooBar()
,将同时影响引用
包含在原始列表和新列表中,因为它们 相同
参考。
您需要查看使用 deepcopy()
(请参阅 复制模块的 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
使用双端队列有助于将大小上限保持在 5 个条目,而无需执行 所有的洗牌自己。