Function changes list values and not variable values in Python
让我们用一个简单的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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"的值保持不变。我已经知道这是因为一个是可变的,另一个不是。但是如何改变代码,使函数不改变列表呢?
例如,要执行类似的操作(为了简单起见,使用伪代码):
1 2 3 4 5 6 7 8 9 10 | a = [1,2,3,...,n] function doSomething(x): do stuff with x return x b = doSomething(a) if someOperation(a) > someOperation(b): do stuff |
编辑:对不起,但是我在嵌套列表中还有一个问题。请参阅此代码:
1 2 3 4 5 6 7 8 9 10 11 | 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,但这些值也是列表,因此对于列表中的每个列表,操作都必须加倍。如何对嵌套列表执行此操作?
python变量包含指向对象的指针或引用。所有值(甚至整数)都是对象,赋值会更改变量以指向不同的对象。它不会在变量中存储新的值,它会更改变量以引用或指向其他对象。由于这个原因,许多人说python没有"变量",它有"名称",并且
在
在
如果不想更改传入的列表,请复制并更改。然后,您的函数应该返回新列表,因为它是创建新对象的操作之一,如果不返回新对象,新对象将丢失。您可以这样做作为函数的第一行:例如
创建列表的副本。使用
1 2 3 4 5 6 7 8 9 | >>> 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] |
或者,您可以在函数中创建一个新列表
1 2 3 4 5 | >>> def plusOne(y): newList = [] for elem in y: newList.append(elem+1) return newList |
你也可以像其他人指出的那样使用理解。
1 2 | >>> def plusOne(y): return [elem+1 for elem in y] |
可以使用切片表示法传递列表的副本:
1 | print plusOne(y[:]), y |
或者更好的方法是在函数本身中创建列表的副本,这样调用方就不必担心可能的修改:
1 2 | def plusOne(y): y_copy = y[:] |
改为研究
或者正如@abarnet在注释中指出的那样,您可以修改函数以使用
1 | return [x + 1 for x in y] |
只需创建一个包含所需值的新列表,然后返回该列表即可。
1 2 | def plus_one(sequence): return [el + 1 for el in sequence] |
要回答您编辑的问题:
复制嵌套的数据结构称为深度复制。要在python中执行此操作,请在
正如其他人所指出的,如果不想修改原始列表,您应该使用
1 2 3 4 5 | def plusOne(y): y2 = list(y) # copy the list over, y2 = y[:] also works for i, _ in enumerate(y2): y2[i] += 1 return y2 |
但是,您可以通过列表理解来实现您想要的输出。
1 2 | def plusOne(y): return [i+1 for i in y] |
这将迭代
您可以通过生成一个函数并通过map函数调用这个函数来实现这一点,map函数将调用add函数并给它赋值,之后它将打印新值,如下所示:
1 2 3 | def add(x): return x+x print(list(map(add,[1,2,3]))) |
或者您可以使用(*range)函数,这样很容易做到:
1 | print ([i+i for i in [*range (1,10)]]) |