等字符串自动更新(列表对象引用)

时间:2015-01-02 07:05:15

标签: python list object-reference

我最近参加了大学考试,我被问到这个课程的输出是什么:

def fun(x):
    y=x
    x.append(4)
    print(str(x)+" "+str(y))

fun(["one","two",3,5.0])

我回答说y列表是["one","two", 3,5.0],在向它附加4之后,x列表将等于相同但在其末尾有4。令我惊讶的是,当我打印两个列表时,即使在两个列表之间建立相等之后执行了x列表更新,它们也是相同的。为什么会这样?

谢谢

5 个答案:

答案 0 :(得分:3)

如果列表x到y,您已经提供了参考。因此列表x中的任何更改也会影响列表y。

y=x

例如:

>>> x = ["one","two",3,5.0]
>>> y = x
>>> x[3] = 4
>>> x
['one', 'two', 3, 4]
>>> y
['one', 'two', 3, 4]

这里x和y都具有相同的身份。

>>> x is y
True
>>> id(x)
3073118540L
>>> id(y)
3073118540L

您可以使用swampy模块更好地理解这一点:

>>> from swampy.Lumpy import Lumpy
>>> lump = Lumpy()
>>> x = ["one","two",3,5.0]
>>> y = x
>>> x[3] = 4
>>> lump.object_diagram()

enter image description here


您可以通过将列表x复制到列表y来实现您的期望:

>>> x = ["one","two",3,5.0]
>>> y = x[:]
>>> x.pop()
5.0
>>> x
['one', 'two', 3]
>>> y
['one', 'two', 3, 5.0]

因此,通过将内容从x复制到y,它们不具有相同的标识:

>>> id(x)
3073240428L
>>> id(y)
3073240588L
>>> x is y
False

使用沼泽:

>>> from swampy.Lumpy import Lumpy
>>> lump = Lumpy()
>>> x = ["one","two",3,5.0]
>>> y = x[:]
>>> lump.draw_object()
>>> lump.object_diagram()

enter image description here

有关更好的说明,请访问How do I copy an object in Python?

答案 1 :(得分:1)

实际上xy是引用对象的标签,因此当您指定y=x时,您会对一个对象进行引用,因此当您更改其中一个对象时,您需要更改主对象

另外,您可能会注意到xy是您更改主要对象的append之类的内部更改时的局部变量,但是如果您使用赋值python则创建一个新对象:

>>> def fun(x):
...     y=x
...     x=x+[3]
...     print(str(x)+" "+str(y))
... 
>>> fun(["one","two",3,5.0])
['one', 'two', 3, 5.0, 3] ['one', 'two', 3, 5.0]

对象的就地更改不会将名称分类为本地人;只有实际的名字 作业。例如,如果将名称L分配给a的顶级列表 模块,函数中的语句L = X会将L归类为本地,但L.append(X) 将不会。在后一种情况下,我们正在更改L引用的列表对象,而不是L本身 - 像往常一样在全局范围内找到L,Python很乐意在不需要的情况下修改它 全局(或nonlocal)声明。像往常一样,它有助于保持区​​别 名称和对象清除:更改对象不是对名称的赋值。(来自学习python by mark lutz

class A:
  global L
  L=[1,2]
  def b(self):
     L=[0,0]
     return L
  def c(self):
     L.append(5)
     return L

a=A()
print a.b()

print a.c()

结果:

[0, 0]
[1, 2, 5]

答案 2 :(得分:0)

因为列表是mutable个对象。见Python Data Model

In [1]: a = [1]

In [3]: b = a

In [4]: b
Out[4]: [1]

In [5]: b.append(2)

In [6]: a
Out[6]: [1, 2]

In [7]: b
Out[7]: [1, 2]

In [8]: id(a), id(b)
Out[8]: (140260765233376, 140260765233376)

答案 3 :(得分:0)

因为名称yx

绑定在同一列表中
y = x

这是一幅很棒的图片:

 x   y
 |  /
 | /
["one", "two", 3, 5.0]

x.append(4)

 x   y
 |  /
 | /
["one", "two", 3, 5.0, 4]

答案 4 :(得分:0)

您可以尝试以下示例。它将帮助您获得赋值运算符和复制(浅),深度复制等方法之间的差异。

>>> import copy
>>> l1 = [1,2, [1,2]]
>>> l1
[1, 2, [1, 2]]
#Create l2, l3, l4 by copy, deepcopy method and normal assignment.
>>> l2 = copy.copy(l1)
>>> l3 = copy.deepcopy(l1)
>>> l4 = l1
>>> l2
[1, 2, [1, 2]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2]]
#-----------------------Now Append value to l1
>>> l1.append(9)
>>> l1
[1, 2, [1, 2], 9]
>>> l2
[1, 2, [1, 2]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2], 9]
#-----------------------Now Append value to l1[2]
>>> l1[2].append(5)
>>> l1
[1, 2, [1, 2, 5], 9]
>>> l2
[1, 2, [1, 2, 5]]
>>> l3
[1, 2, [1, 2]]
>>> l4
>>> [1, 2, [1, 2, 5], 9]
#------------------------