我正在尝试理解当作为参数传递给函数时如何处理列表。所以我做的是以下内容:
我初步确定了一个清单:
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)
我认为这份名单是作为参考传递的;所以无论我们对函数内的列表做什么都会改变从主程序传递的原始函数。因此,对于案例(2),我期待以下结果:
print ll # [11] # case(2) expected result
我在这里错过了什么吗?
答案 0 :(得分:7)
ar += [11]
不只是一项任务。它是一个方法调用(称为__iadd__
的方法)。当Python执行该行时,它会调用该方法,然后将ar
分配给结果。 __iadd__
的list
方法会修改当前的list
。
ar = [11]
是一个作业,因此它只是更改了本地名称ar
的值。但是函数内的ar
名称与ll
变量的值之间没有任何关联。
您可能需要以下内容:
ar[:] = [11]
答案 1 :(得分:5)
您必须区分对象和对象的名称。 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]
你能说出原因吗?
答案 2 :(得分:2)
+=
之类的增强作业会执行正常=
作业无法执行的操作。当您指定名称时,如下所示:
ar = [11]
这是对ar
名称的操作。 ar
之前引用的列表对象未更改,因此当您在函数外部执行print ll
时,您会看到原始列表。
当你这样做时
ar += [11]
这与
并不完全相同ar = ar + [11]
如果您ar = ar + [11]
ll
,+=
将保持不变。但是,ar
请求11
引用的列表,如果可能,应通过修改自己的状态来执行操作,而不是通过创建新列表。由于列表是可变的,因此列表会将自身修改为具有新的ll
元素,并且通过group by
变量可以看到此更改。