让我们用一个简单的代码:
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,但这些值也是列表,因此对于列表中的每个列表,操作都必须加倍。如何使用嵌套列表执行此操作?
Python变量包含指向对象的指针或引用。所有值(甚至整数)都是对象,赋值将变量更改为指向不同的对象。它不会在变量中存储新值,它会将变量更改为引用或指向不同的对象。由于这个原因,许多人说Python没有“变量”,它有“名称”,而
=
操作不是“为变量赋值”,而是“将名称绑定到对象”在
plusOne
中,您正在修改(或“变异”)y
的内容,但永远不会更改y
本身所指的内容。它始终指向同一个列表,即您传递给函数的列表。全局变量y
和局部变量y
引用同一列表,因此使用这两个变量可以看到更改。由于更改了传入对象的内容,实际上没有理由返回y
(事实上,返回None
正是Python本身对这样修改列表“就地”的操作所做的——值由创建新对象的操作返回,而不是对现有对象进行变异)。在
plusOne2
中,您正在更改局部变量a
,以引用另一个整数对象3
。(“将名称a
绑定到对象3
。”)全局变量a
不会因此而更改,而是继续指向2
。如果不想更改传入的列表,请复制并更改该列表。然后,您的函数应该返回新列表,因为它是创建新对象的操作之一,如果不返回新对象,新对象将丢失。您可以在函数的第一行执行此操作:
x = x[:]
例如(正如其他人指出的那样)。或者,如果让函数以任何一种方式调用都是有用的,那么如果他想要复制,您可以让调用方传入x[:]
。创建列表的副本。使用
testList = inputList[:]
。查看代码或者,您可以在函数中创建一个新列表
你也可以像其他人指出的那样使用理解。
可以使用切片符号传递列表的副本:
或者更好的方法是在函数本身中创建list的副本,这样调用者就不必担心可能的修改:
而是在
y_copy
上工作。或者正如@abarnet在注释中指出的,您可以修改函数以使用
list comprehension
,这将创建一个新的列表:相关问题 更多 >
编程相关推荐