函数在Python中更改列表值而不是变量值

Tim*_*Tim 5 python variables function list nested-lists

我们来看一个简单的代码:

y = [1,2,3]

def plusOne(y):
    for x in range(len(y)):
        y[x] += 1
    return y

print plusOne(y), y


a = 2

def plusOne2(a):
    a += 1
    return a

print plusOne2(a), a
Run Code Online (Sandbox Code Playgroud)

'y'的值发生变化但值'a'保持不变.我已经知道这是因为一个是可变的而另一个不是.但是如何更改代码以使函数不更改列表?

例如,要做类似的事情(为了简单起见,使用伪代码):

a = [1,2,3,...,n]

function doSomething(x):
    do stuff with x
    return x

b = doSomething(a)

if someOperation(a) > someOperation(b):
    do stuff
Run Code Online (Sandbox Code Playgroud)

编辑:抱歉,我在嵌套列表上另一个问题.看到这段代码:

def change(y):
    yN = y[:]
    for i in range(len(yN)):
        if yN[i][0] == 1:
            yN[i][0] = 0
        else:
            yN[i][0] = 1
    return yN

data1 = [[1],[1],[0],[0]]
data2 = change(data1)
Run Code Online (Sandbox Code Playgroud)

在这里它不起作用.为什么?再说一遍:如何避免这个问题?我理解为什么它不起作用:yN = y [:]将y的值复制到yN,但值也是列表,因此对于列表中的每个列表,操作必须加倍.如何使用嵌套列表执行此操作?

kin*_*all 15

Python变量包含对象的指针或引用.所有值(甚至整数)都是对象,赋值将变量更改为指向不同的对象.它不会变量中存储新值,它会更改变量以引用或指向其他对象.出于这个原因,许多人说Python没有"变量",它有"名称",=操作不"为变量赋值",而是"将名称绑定到对象".

plusOne您要修改(或"突变")的内容y,但从来没有改变什么y本身指.它保持指向同一个列表,即传递给函数的列表.全局变量y和局部变量y引用相同的列表,因此使用任一变量都可以看到更改.由于您更改了传入的对象的内容,因此实际上没有理由返回y(实际上,返回None是Python本身对此类操作所做的操作,即"就地"修改列表 - 值由操作返回创建新对象而不是改变现有对象.

plusOne2您正在更改局部变量a以引用不同的整数对象,3.("将名称绑定a到对象3.")全局变量a不会被此更改并继续指向2.

如果您不想更改传入的列表,请复制它并更改它.然后你的函数应该返回新的列表,因为它是创建新对象的那些操作之一,如果你不返回它,新对象将会丢失.您可以将此作为函数的第一行:x = x[:]例如(正如其他人指出的那样).或者,如果以任一方式调用该函数可能有用,则可以让调用者传入,x[:]如果他想要复制.


Suk*_*lra 6

创建列表的副本.用testList = inputList[:].看代码

>>> def plusOne(y):
        newY = y[:]
        for x in range(len(newY)):
            newY[x] += 1
        return newY

>>> y = [1, 2, 3]
>>> print plusOne(y), y
[2, 3, 4] [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

或者,您可以在函数中创建新列表

>>> def plusOne(y):
        newList = []
        for elem in y:
            newList.append(elem+1)
        return newList
Run Code Online (Sandbox Code Playgroud)

您也可以像其他人指出的那样使用理解.

>>> def plusOne(y):
        return [elem+1 for elem in y]
Run Code Online (Sandbox Code Playgroud)