2015-07-03 67 views
4

我想了解如何将列表作为参数传递给函数时进行处理。所以我所做的是以下几点:传递给函数时列表发生了什么?

我初始化列表:

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

'ar = [11]'将名称分配给**完全不同的对象**。如果要替换列表的全部内容,请尝试'ar [:] = [11]'。 – jonrsharpe

+3

我发现你选择名称和值('ll'和'11')令人不安... – rodrigo

+0

对于名称和值的选择,我很抱歉。 – rnels12

回答

7

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

ar = [11]分配,因此它只是改变了当地的名ar的价值。但函数内的ar名称与ll变量的值之间没有关联。

你可能想是这样的:

ar[:] = [11] 
+0

严格地说,'ar + = [11]'实际上仍然是一项任务;它需要像'ar =(1,2,3); ar + =(11,)'工作。 – user2357112

+0

@ user2357112你说得对,我简直太简单了。修订。 – Bakuriu

+0

感谢您的帮助。我想我现在明白了。 – rnels12

2

+=增强的任务做一些正常=分配没有做。当您指定一个名字,像这样:

ar = [11] 

这对ar名称的操作。 ar以前提到的列表对象是不变的,所以当你做print ll以外的功能时,你会看到原来的列表。

当你

ar += [11] 

这并不完全等同于

ar = ar + [11] 

如果你没有ar = ar + [11]ll将保持不变。但是,+=请求在可能的情况下,ar所引用的列表应通过修改其自身状态来执行操作,而不是通过创建新列表来执行操作。由于列表是可变的,因此列表会自行修改以使其具有新的11元素,并且通过ll变量可以看到此更改。

+0

感谢您的解释! – rnels12

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] 

你能告诉为什么?

+0

是因为名称a&c现在用于引用同一个对象吗? 感谢btw的解释。 – rnels12

相关问题