【问题标题】:Why does function modify list and how can I keep it from happening?为什么函数会修改列表以及如何防止它发生?
【发布时间】:2019-10-25 14:06:00
【问题描述】:

我在 Python 3.7.x 中调用一个函数并将一个列表传递给它。我确实想要修改列表。在函数内部,我复制列表并对其进行修改。

函数完成后,传递给函数的原始列表已被修改。为什么会发生这种情况,我该如何预防?

这里是代码

def append_string(alist, astring):
    a_new_list = alist
    a_new_list.append(astring)
    return a_new_list
my_list = ["a", "b"]
my_string = "c"
my_new_list = append_string(my_list, my_string)
print(my_list)
print(my_new_list)

这是输出。请注意,my_list 已被修改。

['a', 'b', 'c']
['a', 'b', 'c']

我希望 my_list 保持不变,而 my_new_list 包含值的串联。

【问题讨论】:

    标签: python-3.x


    【解决方案1】:

    a_new_list = alist 不会复制该列表,它只是为同一列表添加一个新名称引用。

    要复制列表,您可以从几个选项中进行选择

    a_new_list = alist[:]
    
    from copy import copy
    a_new_list = copy(alist)
    

    编辑

    写完这篇文章后,我发现这里有一个重复的问题:How to clone or copy a list?。那里接受的答案更好,更详细并且列出了我实际上不知道的更多选项。

    【讨论】:

    • 你应该注意使用copy会创建一个浅拷贝。对于一维数字列表,这不是问题。但是,如果您有列表列表,那将是一个问题。例如:a=[0]; b=[a]; c=copy(b)。然后c is b 返回 False(如预期),但 c[0] is b[0] 返回 True --> 内部列表没有被复制。如果这是一个问题,请改用copy.deepcopy
    【解决方案2】:

    让我试试,

    在您的函数中,您将一个列表和一个对象作为输入。将项目附加到提供的输入后,返回列表。

    正在发生的事情是,

    1. 您正在向函数发送列表的 C 指针
    2. 您将项目添加到列表中
    3. 您正在返回列表的 C 指针
    
    >>> def append_string(alist, astring):
    ...     a_new_list = alist
    ...     a_new_list.append(astring)
    ...     print(id(a_new_list)) # print the list's id
    ...     return a_new_list
    ...
    >>>
    >>> alist = ['a', 'b', 'c']
    >>> id(alist)
    140215330632840
    >>>
    >>> 
    >>> append_string(alist, 'd') # this 
    140215330632840
    ['a', 'b', 'c', 'd']
    >>>
    >>> id(append_string(alist, 'd'))
    140215330632840
    140215330632840
    >>>
    

    如您所见,列表中的id 只是进出函数。要获得列表的精确副本,您可以使用 python 内置库中的 deepcopy 函数 copy

    注意: id 函数 - 返回对象的标识。这保证在同时存在的对象中是唯一的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多