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

2024-09-24 22:28:37 发布

您现在位置:Python中文网/ 问答频道 /正文

让我们用一个简单的代码:

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

值“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

编辑:抱歉,我在嵌套列表中还有一个问题。请参阅以下代码:

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)

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


Tags: 代码in列表forlenreturndefrange
3条回答

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

plusOne中,您正在修改(或“变异”)y内容,但永远不会更改y本身所指的内容。它始终指向同一个列表,即您传递给函数的列表。全局变量y和局部变量y引用同一列表,因此使用这两个变量可以看到更改。由于更改了传入对象的内容,实际上没有理由返回y(事实上,返回None正是Python本身对这样修改列表“就地”的操作所做的——值由创建新对象的操作返回,而不是对现有对象进行变异)。

plusOne2中,您正在更改局部变量a,以引用另一个整数对象3。(“将名称a绑定到对象3。”)全局变量a不会因此而更改,而是继续指向2

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

创建列表的副本。使用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]

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

>>> def plusOne(y):
        newList = []
        for elem in y:
            newList.append(elem+1)
        return newList

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

>>> def plusOne(y):
        return [elem+1 for elem in y]

可以使用切片符号传递列表的副本:

print plusOne(y[:]), y

或者更好的方法是在函数本身中创建list的副本,这样调用者就不必担心可能的修改:

def plusOne(y):
    y_copy = y[:]

而是在y_copy上工作。


或者正如@abarnet在注释中指出的,您可以修改函数以使用list comprehension,这将创建一个新的列表:

return [x + 1 for x in y]

相关问题 更多 >