假设我有list参数的功能,并且在我的体内,我想通过将数组元素复制到列表来修改传递列表:
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
?
答案 0 :(得分:17)
如果您为变量list_arg
指定了某些内容,那么它将从那时开始指向新值。 之前指向该分配(您的原始列表)的值将保持不变。
如果您为该列表的元素分配了一些内容,则会更改原始列表:
list_arg[:] = list(a)
这将使您的代码按照您的意愿运行。
但请记住,就地更改很难理解,可能会让下一位必须维护代码的开发人员感到困惑。
答案 1 :(得分:3)
您可以对列表进行操作以更改其值(例如,向其添加内容或设置其值),但只有在对传入对象的引用进行操作时,更改才会反映在函数外部:
def function1 (list_arg):
list_arg.append(5)
如果您在执行此操作时遇到问题,请打印id
s:
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
没有影响,因为它只是为{{1}分配了一个不同的对象}}
答案 2 :(得分:1)
您正在更改对局部变量的引用。当你以这种方式传入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)
答案 3 :(得分:1)
我认为你问的是为什么在致电f(a)
后,当f
重新分配你通过的a
时,a
仍然是“旧”{{}你通过了。
这样做的原因是Python如何处理变量并将它们传递给函数。它们通过引用传递 ,但引用按值传递 (意味着创建了一个副本)。这意味着a
中的引用实际上是您传递的引用的副本。这再次意味着如果您在函数内部重新分配变量。它是仅存在于函数内部的局部变量;重新分配它不会改变外部范围内的任何内容。
现在,如果您不是在f
内重新分配局部变量/引用(这将无效,因为它是副本)对它执行可变操作,例如f
,列表为您append()
完成后,pass将发生变化。
另请参阅问题How do I pass a variable by reference?,该问题将更详细地处理问题和可能的解决方案。
TL; DR:在函数内重新分配变量不会更改作为函数外部参数传递的变量。但是,对变量执行可变操作会改变它。