蟒蛇; 修改函数内的列表

rob*_*rto 18 python list

假设我有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]
Run Code Online (Sandbox Code Playgroud)

这样做时,它不起作用.执行后function1(list1),list1保持不变.那么,如何使用与数组相同的元素(数字)function1返回? list1a

Alf*_*lfe 23

如果为变量赋值list_arg,则从那时起指向新值.该分配之前指向的值(您的原始列表)将保持不变.

相反,如果您为该列表的元素指定了一些内容,则会更改原始列表:

list_arg[:] = list(a)
Run Code Online (Sandbox Code Playgroud)

这将使您的代码按您的需要工作.

但请记住,就地更改很难理解,并且可能会使下一个必须维护代码的开发人员感到困惑.

  • 鉴于返回一个新的(略有变化的)列表实际上是一个非常不同的操作(需要更多的内存和时间,具体取决于列表的大小),人们无法真正比​​较两者并说一个比另一个更好。如果程序确实需要更改列表,则其名称应清楚地反映这一点。反映这一点的典型短语是“in_place”。 (4认同)

tom*_*m10 6

您可以对列表进行操作以更改其值(例如,向其附加某些内容或设置其值),但只有在对传入对象的引用进行操作时,更改才会反映在函数之外:

def function1 (list_arg):
   list_arg.append(5)
Run Code Online (Sandbox Code Playgroud)

如果您在执行此操作时有疑问,请打印出ids:

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
Run Code Online (Sandbox Code Playgroud)

印刷:

1 4348413856
2 4348413856
3 4348411984
['a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)

也就是说,x就地更改,但分配给函数的局部变量list_arg对 没有影响x,因为它只是将不同的对象分配给list_arg


Håv*_*d S 5

我想你问就是为什么呼叫后f(a),当f重新分配a你过去了,a依然是“老字号” a你通过。

原因是Python如何对待变量并将其传递给函数。它们通过引用传递,但是引用通过传递(表示创建了副本)。这意味着您拥有的引用f实际上是您传递的引用的副本。这再次意味着如果您在函数内部重新分配变量。它是仅在函数内部存在的局部变量。重新分配它不会改变外部作用域。

现在,如果您不是在内部重新分配局部变量/引用f(由于它是副本,将不起作用),而是对其执行可变操作,例如append(),则您传递的列表将在f完成后更改。

另请参阅问题如何通过引用传递变量?进一步详细处理问题和可能的解决方案。

TL; DR:在函数内部重新分配变量不会更改您作为函数外部参数传递的变量。但是,对该变量执行可变操作将对其进行更改。