函数在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一个新列表