以下是一些代码:
li=[1,2,3]
def change(l):
l[2]=10
change(li)
print li
[1, 2, 10]
但我想要这个:
li=[1,2,3]
def change(l):
l=[1,2,10]
change(li)
print li
[1,2,3]
出于某种原因,我必须在方法中更改整个列表,我该如何实现?有什么不对或我的错误?
答案 0 :(得分:2)
如果要更改方法内的整个列表,可能需要创建副本并返回:
def change(li):
new_list = li[:] #copy
new_list[2] = 10
return new_list
li = [1,2,3]
new_lst = change(li) #new_lst = [1,2,10]
如果您不想返回列表,但想要在适当的位置进行修改,则可以使用切片分配(*警告:这不常见):
def change(li):
li[:] = [1,2,10]
li = [4,5,6]
change(li)
print(li) #[1, 2, 10]
答案 1 :(得分:1)
像这样:
li = [1, 2, 3]
def change(l):
l[:] = [1, 2, 10]
change(li)
print li # [1, 2, 10]
你的方法不起作用的原因是在python中,变量只是引用对象的名称。当您编写l = [1, 2, 10]
时,您重新绑定名称l
以引用您刚刚创建的新列表,旧列表将保持不变并仍由全局变量{{1}引用}。
上面的代码改为使用slice assignment修改li
指向的对象。
正如mgilson在他的回答中指出的那样,你应该非常清楚该函数实际修改了传入的参数。如果没有,一个毫无戒心的程序员可能会传递一个他打算稍后使用的列表,只是发现其中的所有内容都已丢失。给你的函数一个表示修改的名称(就像你已经完成的那样)而不是从中返回任何东西都是这些函数的常用指标,例如random.shuffle
。
为了达到dict的相同效果,documentation告诉我们这样做:
l
答案 2 :(得分:0)
文档: List Aliasing — How to Think like a Computer Scientist (2nd editon)
您可以利用Python的列表别名(对于初学者来说是common gotcha)。
当您将li
传递给change
函数时,l
别名为li
,即它们都指向内存中的同一个对象,而更改一个会更改另一个。但是当你执行l = [1, 2, 10]
时,l
指向另一个列表,你就会失去别名魔法。要解决此问题,您可以使用切片操作替换为完整列表,如下所示:
li = [1, 2, 3]
def change(l):
l[:] = [1, 2, 10] # doesn't make a new list
change(li) # preserves aliasing
print li # returns [1, 2, 10]
您在函数内对l
所做的更改不会应用于外部的li
列表。您可以使用全局来影响您尝试更改的li
列表:
li = [1, 2, 3]
def change():
global li
li = [1, 2, 10] # use this
li[2] = 10 # or this, up to you
change()
print li # returns [1, 2, 10]
答案 3 :(得分:0)
执行以下操作时:
def change(l):
l=[1,2,10]
您实际上正在更改l
指向的列表。您需要将传入的列表实例更改为change
。您可append
向它,pop
,等等,您的更改将转到您传入的列表中。如果您将change
功能更改为我拥有的功能,例子可行。
def change(l):
l[:] = [1,2,10]
答案 4 :(得分:0)
在此代码中,l作为整体的公共对象工作,因此您可以通过提供对象内存位置的id()进行检查。 这就是为什么你得到最后一个输出[1,2,10]
l = [1, 2, 3]
print id(l)
def change(l):
l[:] = [1, 2, 10]
print id(l)
change(l)
print l
print id(l)
如果您想要所需的输出,请使用提供diffident对象的deepcopy来运行。
from copy import deepcopy
l = [1, 2, 3]
print id(l)
def change(l):
l[:] = [1, 2, 10]
print id(l)
change(deepcopy(l))
print l
print id(l)