提问人:Tim 提问时间:7/17/2013 最后编辑:Tim 更新时间:2/5/2019 访问量:19376
函数更改 Python 中的列表值而不是变量值 [duplicate]
Function changes list values and not variable values in Python [duplicate]
问:
让我们用一个简单的代码:
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,但这些值也是列表,因此必须对列表中的每个列表进行加倍操作。如何使用嵌套列表执行此操作?
答:
创建列表的副本。用。查看代码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
或者更好的方法是在函数本身中创建列表的副本,这样调用者就不必担心可能的修改:
def plusOne(y):
y_copy = y[:]
并继续工作。y_copy
或者正如@abarnet在注释中指出的那样,您可以修改要使用的函数,这将创建一个新列表:list comprehension
return [x + 1 for x in y]
Python 变量包含指向对象的指针或引用。所有值(甚至整数)都是对象,赋值会更改变量以指向不同的对象。它不会在变量中存储新值,而是更改变量以引用或指向不同的对象。出于这个原因,许多人说 Python 没有“变量”,它有“名称”,并且该操作不是“为变量赋值”,而是“将名称绑定到对象”。=
在你修改(或“改变”)内容,但从不改变它本身所指的内容。它始终指向同一个列表,即您传递给函数的列表。全局变量和局部变量引用同一个列表,因此使用任一变量都可以看到更改。由于您更改了传入的对象的内容,因此实际上没有理由返回(实际上,返回是 Python 本身对此类“就地”修改列表的操作所做的——值由创建新对象而不是更改现有对象的操作返回)。plusOne
y
y
y
y
y
None
在您要更改局部变量以引用不同的整数对象时,.(“将名称绑定到对象。”)全局变量不会因此而改变,而是继续指向 。plusOne2
a
3
a
3
a
2
如果不想更改传入的列表,请复制该列表并对其进行更改。然后,您的函数应该返回新列表,因为它是创建新对象的操作之一,如果您不返回新对象,则新对象将丢失。您可以将其作为函数的第一行执行:例如(正如其他人所指出的)。或者,如果以任何一种方式调用函数可能很有用,则如果调用者想要创建副本,则可以让调用者传入。x = x[:]
x[:]
只需创建一个包含所需值的新列表,然后返回该列表即可。
def plus_one(sequence):
return [el + 1 for el in sequence]
正如其他人所指出的,如果您不想修改原始列表,则应使用或复制列表。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
要回答您编辑的问题,请执行以下操作:
复制嵌套数据结构称为深度复制。要在 Python 中执行此操作,请在复制
模块中使用。deepcopy()
你可以通过做一个函数,然后通过map函数调用这个函数来做到这一点, map 函数将调用 add 函数并为其赋值,然后它将像这样打印新值:
def add(x):
return x+x
print(list(map(add,[1,2,3])))
或者您可以使用(*range)函数,就像那个例子一样很容易做到:
print ([i+i for i in [*range (1,10)]])
评论