为什么我的函数会覆盖作为参数传递的列表? [英] Why does my function overwrite a list passed as a parameter?

查看:73
本文介绍了为什么我的函数会覆盖作为参数传递的列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个将列表作为参数的函数.它将对列表进行混洗,替换第一个元素,然后返回新列表.

I have created a function that takes a list as a parameter. It shuffles the list, replaces the first element and returns the new list.

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.

The shuffle has no impact on my question. However, I was surprised to see that the returned importedList overwrites the original 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']

通过在函数中复制列表,我发现了一种解决方法,但效率似乎很低.

I have found a workaround by copying the list within the function, but it seems inefficient.

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?例如,如果是字符串,则不会发生这种情况.

My question is why does the function replace the firstList? This would not happen if it were a string for example.

string="a"

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


>>> string
'a'

>>> substituteString(string)
'b'

>>> string
'a'

推荐答案

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

Strings, Ints, Tuples are immutable python types, so when you perform operations that change one of these types the new corresponding object is effectively created in memory each time. (Or you get an error if trying to change those in-place.)

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

Lists and dictionaries are mutable python types, so when you perform operations that change one of these types, the object stays the same, but it's parts (i.e., list elements) get changed.

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

So when you want to change a list, but want to leave the original intact you have to copy it yourself. Important thing, that there're two types of copying - shallow copy and deep copy.

可以像这样进行浅拷贝:

Shallow copy can be done like so:

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

深层复制是通过以下方式完成的:

Deep copy is done in the following way:

import copy
list_b = copy.deepcopy(list_a)

深层副本和浅层副本之间的区别是...

The difference between deep copy and shallow copy is...

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

When doing shallow copy, if mutable object contains other mutable objects, only the top one is copied. I.e. if a list contains other list, if top list is copied and then the inner list is changed in the copy, effectively the inner list will be changed both in the copy and in the original, because it's the same object in memory that is referenced in two different lists. Basicly shallow copy creates a new object with the same references stored in original object.

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

When doing deep copy, if mutable object contains other mutable objects, then inner mutable objects are copied too. I.e. as in previous example, if you change inner list in the copy, it changes only in the copy and the original is not affected. So deep copy copies everything, creates new structure in memory for everything in the object being copied, and not just references.

这篇关于为什么我的函数会覆盖作为参数传递的列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆