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

Python 自动更新相等字符串(列表对象引用),python,list,object-reference,Python,List,Object Reference,我最近参加了一次大学考试,有人问我这个项目的产出是什么: def fun(x): y=x x.append(4) print(str(x)+" "+str(y)) fun(["one","two",3,5.0]) 我回答说y列表将是[“一”,“二”,3,5.0],在它后面加上4之后,x列表将等于相同的,但末尾有一个4。令我惊讶的是,当我打印两个列表时,它们是相等的,即使在两个列表之间建立相等之后执行了x列表更新。为什么会这样 谢谢事实上,x和y是引用对象的标签,因此当

我最近参加了一次大学考试,有人问我这个项目的产出是什么:

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

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


谢谢

事实上,
x
y
是引用对象的标签,因此当您指定
y=x
时,您将两个引用装箱到一个对象,因此当您更改其中一个对象时,您将更改主对象

另外,您可能会注意到,
x
y
是局部变量,当您进行诸如
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被分配给位于 模块中,函数中的语句
L=X
将L分类为本地,但
L.append(X)
不会。在后一种情况下,我们正在更改L引用的list对象,而不是L本身- L像往常一样位于全局范围内,Python很乐意修改它,而无需 全局(或
非局部
)声明。与往常一样,它有助于保持两者之间的区别 名称和对象清除:更改对象不是对名称的赋值

结果:

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

实际上,
x
y
是引用对象的标签,因此当您指定
y=x
时,您将两个引用装箱到一个对象,因此当您更改其中一个对象时,您将更改主对象

另外,您可能会注意到,
x
y
是局部变量,当您进行诸如
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被分配给位于 模块中,函数中的语句
L=X
将L分类为本地,但
L.append(X)
不会。在后一种情况下,我们正在更改L引用的list对象,而不是L本身- L像往常一样位于全局范围内,Python很乐意修改它,而无需 全局(或
非局部
)声明。与往常一样,它有助于保持两者之间的区别 名称和对象清除:更改对象不是对名称的赋值

结果:

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

如果列表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
您可以使用以下模块更好地理解此内容:


通过如下方式将列表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()


如需更好的解释,请访问此处

如果列表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
您可以使用以下模块更好地理解此内容:


通过如下方式将列表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()


要获得更好的解释,请访问此处,因为列表是可变的对象。看


因为列表是可变的对象。看


因为名称
y
x

y = x
这是一幅很好的图画,展示了它的外观:

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



因为名称
y
x

y = x
这是一幅很好的图画,展示了它的外观:

 x   y
 |  /
 | /
["one", "two", 3, 5.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]
#------------------------

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

>>> 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]
#------------------------

可能重复的可能重复的您能否提供一个示例,如果将名称L分配给模块顶部的列表,该示例的外观如何?您能否提供一个示例,如果将名称L分配给模块顶部的列表,该示例的外观如何?