Python列表的行为不符合预期

2024-10-02 14:26:18 发布

您现在位置: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中更改某些内容时,我也会更改历史记录1。我也尝试过使用list()而不是[:],但这会产生相同的结果。我错过了什么?你知道吗


Tags: add列表returnfunctionglobalhistoryeliflst
1条回答
网友
1楼 · 发布于 2024-10-02 14:26:18

您缺少的是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将有助于将cap大小保持在5个条目,而无需这样做 你自己洗牌。你知道吗

相关问题 更多 >