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 个条目,而无需执行 所有的洗牌自己。