我创建了一个将列表作为参数的函数。它会随机排列列表,替换第一个元素,然后返回新列表。
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'
字符串,整数,元组是不可变的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)
深拷贝和浅拷贝之间的区别是…
进行浅表复制时,如果可变对象包含其他可变对象,则仅复制顶部的对象。也就是说,如果一个列表包含其他列表,如果复制了顶部列表,然后在副本中更改了内部列表,则实际上,内部列表将在副本和原始列表中都进行更改,因为它是引用的内存中的同一对象在两个不同的列表中。基本上,浅表复制会使用与原始对象中存储的相同引用创建一个新对象。
在进行深层复制时,如果可变对象包含其他可变对象,那么内部可变对象也会被复制。即,如前面的示例所示,如果您在副本中更改内部列表,则仅在副本中更改,并且原始列表不受影响。如此深层复制会复制所有内容,并在内存中为要复制的对象(而不仅仅是引用)中的所有内容创建新结构。