Python列表变量不通过引用传递吗?

时间:2015-10-31 04:04:51

标签: python list

我对Python中的pass-by-ref和pass-by-value感到困惑。 在下面的代码中,当listB = listA时,listB应该被赋予ListA变量中列表的指针(引用)。对listB的任何更改都应该反映在listA上。但是,在我的测试中并非如此。我做错了代码吗?我正在运行Python 3.4.3

>>> listA = [1,2,3]
>>> listB = listA
>>> listA = [4,5,6]
>>> print(listA, listB)
[4, 5, 6] [1, 2, 3]
>>> listB[0] ='new'
>>> print(listA, listB)
[4, 5, 6] ['new', 2, 3]

4 个答案:

答案 0 :(得分:2)

您完全重新分配listA,因此它与listB之间没有任何关系。

例如:

listA = [2,2,3]

listB = listA

id(listA)
Out[6]: 90404936

id(listB)
Out[7]: 90404936

listA[0]=2

id(listA)
Out[9]: 90404936

listB
Out[10]: [2, 2, 3]

但是当你重新分配listA时,你会丢失id

listA = [3,3,3]

id(listA)
Out[12]: 92762056

但是listB保持相同的ID:

id(listB)
Out[13]: 90404936

答案 1 :(得分:1)

执行listA = [4,5,6]后,listA(已分配给listB)的引用不再指向listA,因为您已完全替换listA新名单。

如果删除该行,您会发现它按预期工作。

答案 2 :(得分:1)

你说:

  

我对python中的pass-by-ref和pass-by-value感到困惑。

实际上,Python不使用 按值调用按引用调用:它使用call-by-object-sharing。这基本上就像按值调用,除了"值"问题实际上是对包含实际值的对象的引用。

从根本上说,在Python中考虑变量的方法是它们实际上是names that can refer to other objects,而不是自己的值。

答案 3 :(得分:0)

对于Python,将名称空间视为由列出名称和地址的2列表实现。另请注意,赋值运算符=会导致右侧被计算,如果尚未表示,则在内存中表示,然后会导致赋值左侧的变量被绑定在符号表中到表示的地址。一次完成一行代码:

listA = [2, 3, 4]

导致2,3和4在特定地址的内存中表示。然后括号使列表对象在内存中表示,包含类的地址,int的长度以及元素的地址数组。最后,名称listA放在名称空间表中,并绑定到该列表对象的地址。

listB = listA

第二个条目listB在命名空间表中生成,并绑定到列表的相同地址。

listA = [4, 5, 6]

在内存中创建三个整数和一个列表的表示,并更改命名空间表中listA引用的地址,并将其绑定到新列表。

listB[0] = 'new'

导致字符串' new'要在内存中表示,然后更改绑定到listB的列表对象,以便该列表的第一个元素现在引用该字符串的地址。

如果listA没有被重新分配给新对象,它仍会指向同一个列表,您会在列表的第一个元素中看到相同的更改是否使用{{ 1}}或listA令牌。