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

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

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,但这些值也是列表,因此对于列表中的每个列表,操作必须加倍。 如何使用嵌套列表执行此操作?

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

plusOne您正在修改(或“改变”) y内容 ,但不会改变y本身引用的内容。 它保持指向相同的列表,你传递给函数的列表。 全局variablesy和局部variablesy引用相同的列表,所以使用任何一个variables都可以看到变化。 由于您更改了传入的对象的内容,因此实际上没有理由返回y (实际上,返回None是Python本身为像这样修改列表的操作所做的操作 – 值将返回创build新对象而不是改变现有对象的操作)。

plusOne2您正在更改局部variablesa以引用不同的整数对象3 。 (“将名字a绑定到对象3 ”)全局variablesa不会被这个变化,而是继续指向2

如果您不想更改传入的列表,请复制并更改该列表。 那么你的函数应该返回新的列表,因为它是创build一个新对象的操作之一,如果你不返回新对象,新对象将会丢失。 你可以做这个函数的第一行:例如x = x[:] (正如其他人指出的那样)。 或者,如果以这种方式调用该函数可能会有用,如果想要复制,可以让调用者通过x[:]传递。

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

或者,您可以在该function中创build一个新列表

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

或者更好的方法是在函数本身中创build列表副本,以便调用者不必担心可能的修改:

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

然后在y_copy工作。


或者如@abarnet在注释中指出的那样,您可以修改该函数来使用list comprehension ,这将完全创build一个新的列表:

 return [x + 1 for x in y] 

只需用你想要的值创build一个新的列表,然后返回。

 def plus_one(sequence): return [el + 1 for el in sequence] 

要回答你编辑的问题:

复制嵌套数据结构称为深度复制 。 要在Python中执行此操作,请在copy模块中使用deepcopy()

正如其他人所指出的,如果您不想修改原始文件,则应该使用newlist = original[:]newlist = list(original)来复制列表。

 def plusOne(y): y2 = list(y) # copy the list over, y2 = y[:] also works for i, _ in enumerate(y2): y2[i] += 1 return y2 

然而,你可以用列表理解来达到你想要的结果

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

这将迭代y的值,并通过为每个值添加一个来创build一个列表