修改函数内部的列表
- 2025-01-16 08:37:00
- admin 原创
- 71
问题描述:
假设我有一个带有列表参数的函数,并且我想在其主体内部通过将数组的元素复制到列表中来修改传递的列表:
def function1 (list_arg):
a = function2() #function2 returns an array of numbers
list_arg = list(a)
list1 = [0] * 5
function1(list1)
list1
[0,0,0,0,0]
这样做是行不通的,执行后function1(list1)
,list1
保持不变。那么,如何让function1
返回的list1
元素(数字)与数组相同呢a
?
解决方案 1:
如果您为变量分配某个值list_arg
,则从那时起它将指向新值。分配之前它指向的值(您的原始列表)将保持不变。
如果你改为将某些内容分配给该列表的元素,这将改变原始列表:
list_arg[:] = list(a)
这将使您的代码按您希望的方式工作。
但请记住,就地更改很难理解,并且可能会使下一位必须维护代码的开发人员感到困惑。
解决方案 2:
我认为您要问的是为什么在调用之后f(a)
,f
重新分配a
您传递的时,a
仍然是您传递的“旧” a
。
原因在于 Python 如何处理变量并将其传递给函数。它们是通过引用传递的,但引用是通过值传递的(意味着创建了一个副本)。这意味着你内部的引用f
实际上是你传递的引用的副本。这再次意味着如果你在函数内部重新分配变量。它是一个只存在于函数内部的局部变量;重新分配它不会改变外部作用域中的任何内容。
现在,如果您不是重新分配内部的局部变量/引用f
(因为它是副本,所以不起作用)而是对其执行可变操作,例如append()
,您传递的列表将在f
完成后发生变化。
另请参阅问题“如何通过引用传递变量?”,其中更详细地讨论了该问题及其可能的解决方案。
TL;DR:在函数内部重新分配变量不会改变您在函数外部作为参数传递的变量。但是,对变量执行可变操作会改变它。
解决方案 3:
您可以对列表进行操作以更改其值(例如,向其中添加一些内容,或设置其值),但只有对传入对象的引用进行操作时,更改才会反映在函数之外:
def function1 (list_arg):
list_arg.append(5)
如果您在执行此操作时有任何疑问,请打印出以下内容id
:
def function1 (list_arg):
print 1, id(list_arg)
list_arg[:] = ["a", "b", "c"]
print 2, id(list_arg)
list_arg = range(10)
print 3, id(list_arg)
x = [1,2,3]
function1(x)
print x
印刷:
1 4348413856
2 4348413856
3 4348411984
['a', 'b', 'c']
也就是说,x
已就地改变,但分配给函数的局部变量list_arg
不会对 产生影响x
,因为 只是将 分配给了一个不同的对象list_arg
。
解决方案 4:
您正在更改对局部变量的引用。当您以这种方式传入 list_arg 时:
def function1 (list_arg):
list_arg 是对底层列表对象的引用。执行此操作时:
list_arg = list(a)
您正在更改函数中 list_arg 的含义。由于函数在此之后立即退出,因此 list_arg = list(a) 不起作用。
如果您想要真正改变对列表的引用,您必须将其分配给函数的结果。
def function1 ():
'a = some array'
return list(a)
list1 = [0] * 5
list1 = function1()
或者您可以修改列表的内容而不更改引用。
def function1(list_arg):
del list_arg[:] # Clears the array
'a = some array'
list_arg.extend(a)