传递给函数时列表会发生啥?

Posted

技术标签:

【中文标题】传递给函数时列表会发生啥?【英文标题】:What happen to a list when passed to a function?传递给函数时列表会发生什么? 【发布时间】:2015-09-21 17:05:40 【问题描述】:

我试图了解将列表作为参数传递给函数时如何处理。所以我做了以下事情:

我初始化了一个列表:

ll = [1,2,3,4] 

并定义一个函数:

def Foo(ar):
    ar += [11]

我将列表传递给函数:

Foo(ll)

当我打印出来时,我得到了:

print ll # [1, 2, 3, 4, 11] #case(1)

到目前为止一切顺利。

现在我修改了函数以重置列表,使其只有一个元素:

def Foo(ar):
    ar = [11]

我想起了语法:

Foo(ll)

当我重新打印它时,它产生了相同的列表:

print ll # [1, 2, 3, 4] # case(2)

我以为列表是作为参考传递的;所以无论我们对函数内部的列表做什么,都会改变从主程序传递的原始函数。所以对于 case(2) 我期待以下结果:

print ll # [11] # case(2) expected result

我错过了什么吗?

【问题讨论】:

ar = [11] 将名称分配给一个完全不同的对象。如果要替换列表的全部内容,请尝试ar[:] = [11] 我发现您选择的名称和值(ll11)令人不安...... 很抱歉选择了名称和值。 【参考方案1】:

ar += [11] 只是一个任务。这是一个方法调用(调用的方法是:__iadd__)。当 Python 执行该行时,它会调用该方法,然后将 ar 分配给结果。 list__iadd__ 方法修改当前的list

ar = [11] 是一个赋值,因此它只是更改本地名称ar 的值。但是函数内部的ar名称和ll变量的值之间没有联系。

你可能想要这样的东西:

ar[:] = [11]

【讨论】:

严格来说ar += [11]其实还是一个赋值;它需要像ar = (1, 2, 3); ar += (11,) 这样的东西才能工作。 @user2357112 你说得对,我过于简单化了。已修改。 感谢您的帮助。我想我现在明白了。 这正是我需要的:ar[:] = [11]【参考方案2】:

您必须区分对象对象的名称。 Python 中的列表是可变对象,因此只要您引用它,就可以更改它们。

名称只是对对象的引用。请记住,从技术上讲,Python 中没有变量,只有名称和对象,并且对象与名称绑定。

因此,考虑到这一点,让我们看看您的代码:

def Foo1(ar):
    ar += [11]

此函数获取一个列表,将其绑定到本地名称ar,然后修改该列表,添加一个新值。

但是这个其他代码:

def Foo2(ar):
    ar = [11]

此函数获取一个列表,绑定到名称ar,然后将名称ar 重新绑定到具有一个值的新列表。在这个函数内部,原始对象是未修改和模糊的。

那么当你这样做时:

a = [1,2,3]

然后调用:

Foo1(a)

修改列表添加一个新值,但是:

Foo2(a)

a 的值没有任何作用。

如果你想编写一个函数来替换列表中的所有内容,你可以这样做:

def Foo3(a):
    a[:] = [11]

此代码不会重新绑定a,而是通过将内容替换为新列表来修改列表。

为了进一步说明我的观点,看这个例子:

a = []
b = []
c = a
a.append(1)
b.append(2)
c.append(3)
print a
print b
print c

它将打印:

[1, 3]
[2]
[1, 3]

你能说出原因吗?

【讨论】:

是不是因为名称 a 和 c 现在用来指代同一个对象?顺便说一句,感谢您的解释。【参考方案3】:

+= 这样的增强赋值可以做一些普通的= 赋值做不到的事情。当您分配一个名称时,如下所示:

ar = [11]

这是对ar 名称的操作。 ar之前引用的列表对象是不变的,所以当你在函数外做print ll时,你会看到原来的列表。

当你这样做时

ar += [11]

这不完全等同于

ar = ar + [11]

如果您使用ar = ar + [11]ll 将保持不变。但是,+= 要求如果可能,ar 引用的列表应该通过修改自己的状态而不是创建新列表来执行操作。由于列表是可变的,因此列表会修改自身以具有新的 11 元素,并且此更改通过 ll 变量可见。

【讨论】:

感谢您的解释!

以上是关于传递给函数时列表会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

在递归函数参数中修改列表时会发生啥

VBA的有参过程定义,形参用啥说明

C语言中,数组名作为函数参数,属于啥传递,为啥?

传递给函数的向量没有被修改

函数返回时堆栈会发生啥? [复制]

当您在 php 中调用函数时,内部会发生啥