有人可以解释以下列表参考问题吗?我没有清楚地理解它。
例如:
>>> a = [1,2,3,4]
>>> a[0:2] = 11,22
>>> a
[11, 22, 3, 4]
>>> b = a[0:2]
>>> b[0:2] = 33,44
>>> b
[33, 44]
>>> a
[11, 22, 3, 4]
为什么a[0:2] = 11,22
更改了列表a
,但b[0:2] = 33,44
没有?不是b
引用a[0:2]
吗?为什么列表的引用正在改变它的值,但是整数引用它会赢?
示例:
>>> a = 1
>>> b = a
>>> a = 2
>>> b
1
答案 0 :(得分:2)
我认为这是不言自明的。
>>> a = [1,2,3,4]
>>> a[0:2] = 11,22
>>> a
[11, 22, 3, 4]
您正在修改a的索引0
和1
的值。因此,索引2
和3
的原始值保持不变。
>>> b = a[0:2]
>>> b[0:2] = 33,44
>>> b
[33, 44]
>>> a
[11, 22, 3, 4]
您已将索引0
和1
的值从a
复制到b
,因此b
只有2个值。然后,您将使用b
覆盖[33,44]
的值。因此,您观察到的结果。
某些数据类型是不可变的(值不能更改),例如数字,字符串,元组。像dict,list这样的数据类型是可变的(值可以更改)
插图
>>> a = [1,2,3,4]
>>> b = a
>>> id(a)
46734952
>>> id(b)
46734952
>>> b[1] = 8
>>> print(b)
[1, 8, 3, 4]
>>> print(a)
[1, 8, 3, 4]
在上述情况中,b
是对a
的引用。即,a
和b
都指向同一个列表。对b
所做的任何更改也会影响a
。这可以使用id
函数进行验证。相同的id
值表示两者都指向同一个对象。
>>> c = a[:]
>>> print(c)
[1, 8, 3, 4]
>>> id(a)
46734952
>>> id(c)
46563240
在上述情况下,a
的切片被分配给c
。因此,制作副本并将其分配给c
。因此id
和a
的{{1}}值不同。
答案 1 :(得分:1)
因为有两种类型的数据
可变数据类型
不可变数据类型
当您更改mutable type
时,您更改了对象,当您更改immutable type
时,您创建了新对象,然后将其分配给变量
答案 2 :(得分:1)
我会一步一步地回答:
a[0:2] = 11,22
与执行a[0] = 11; a[1] = 22
相同。这是常规任务,这里没什么惊喜。
当你这样做时:
b = a[0:2]
您会获得列表的浅层副本。这意味着您将获得一个新列表,并引用每个对象。因为在您的情况下,列表中填充了int
s,所以它本质上也是一个副本。但请考虑这个例子:
让我们定义一个类,它包装int
(或任何其他数据类型,它是python :)),但是是可变的。
In [41]: class num(object):
...: def __init__(self, x):
...: self.x = x
...:
现在我们将像以前一样定义a
,只使用我们的类
In [42]: a = [num(x) for x in range(1,5)]
In [43]: a[0].x
Out[43]: 1
In [44]: a[1].x
Out[44]: 2
现在,我们将a
切片分配到b
。与您的示例相反,当列表保存数字的值时,此处它包含引用,因此您可以说它们是相同的:
In [45]: b = a[0:2]
In [46]: b[0].x
Out[46]: 1
In [47]: b[1].x
Out[47]: 2
所以当我在b
中更改一个时:
In [48]: b[0].x = 3
它反映在a
:
In [50]: a[0].x
Out[50]: 3
但这是一个不同的清单。因此,将新实例分配给列表中的某个位置...
In [49]: b[1] = num(20)
...未反映在a
:
In [51]: a[1].x
Out[51]: 2