一尘不染

为什么我的函数会覆盖作为参数传递的列表?

python

我创建了一个将列表作为参数的函数。它会随机排列列表,替换第一个元素,然后返回新列表。

import random
firstList=["a","b","c","d","e","f","g","h","i"]

def substitution(importedList):
    random.shuffle(importedList)
    importedList[0]="WORD"
    return importedList

改组对我的问题没有影响。但是,我很惊讶地看到返回的importedList覆盖了原始的firstList。

>>> firstList
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

>>> substitution(firstList)
['WORD', 'a', 'b', 'd', 'i', 'c', 'g', 'e', 'h']

>>> firstList
['WORD', 'a', 'b', 'd', 'i', 'c', 'g', 'e', 'h']

通过在函数中复制列表,我找到了一种解决方法,但是效率似乎很低。

import random
firstList=["a","b","c","d","e","f","g","h","i"]
string="a"

def substitutionandcopy(importedList):
    copiedList=importedList[:]
    random.shuffle(copiedList)
    copiedList[0]="WORD"
    return copiedList

我的问题是为什么该函数替换firstList?例如,如果是字符串,则不会发生这种情况。

string="a"

def substituteString(foo):
    foo='b'
    return foo

>>> string
'a'

>>> substituteString(string)
'b'

>>> string
'a'

阅读 150

收藏
2021-01-20

共1个答案

一尘不染

字符串,整数,元组是不可变的python类型,因此,当您执行更改这些类型之一的操作时,每次都会在内存中有效地创建新的对应对象。(或者,如果尝试就地进行更改,则会收到错误消息。)

列表和字典是可变的python类型,因此当您执行更改这些类型之一的操作时,对象保持不变,但是对象的一部分(即列表元素)被更改。

因此,当您想更改列表但又想保留原样时,必须自己复制它。重要的是,有两种复制类型- 浅复制深复制

浅复制可以这样进行:

list_b = list_a[:] #using slice syntax

#or

list_b = list(list_a) #instantiating a new list from iterating over the old one

#or

import copy
list_b = copy.copy(list_a) #using copy module

深度复制通过以下方式完成:

import copy
list_b = copy.deepcopy(list_a)

深拷贝和浅拷贝之间的区别是…

进行浅表复制时,如果可变对象包含其他可变对象,则仅复制顶部的对象。也就是说,如果一个列表包含其他列表,如果复制了顶部列表,然后在副本中更改了内部列表,则实际上,内部列表将在副本和原始列表中都进行更改,因为它是引用的内存中的同一对象在两个不同的列表中。基本上,浅表复制会使用与原始对象中存储的相同引用创建一个新对象。

在进行深层复制时,如果可变对象包含其他可变对象,那么内部可变对象也会被复制。即,如前面的示例所示,如果您在副本中更改内部列表,则仅在副本中更改,并且原始列表不受影响。如此深层复制会复制所有内容,并在内存中为要复制的对象(而不仅仅是引用)中的所有内容创建新结构。

2021-01-20