python列表切片上的整数和引用

时间:2014-10-05 16:04:55

标签: python list reference

有人可以解释以下列表参考问题吗?我没有清楚地理解它。

例如:

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

3 个答案:

答案 0 :(得分:2)

我认为这是不言自明的。

>>> a = [1,2,3,4]  
>>> a[0:2] = 11,22  
>>> a  
[11, 22, 3, 4]    

您正在修改a的索引01的值。因此,索引23的原始值保持不变。

>>> b = a[0:2]  
>>> b[0:2] = 33,44  
>>> b  
[33, 44]  
>>> a  
[11, 22, 3, 4]  

您已将索引01的值从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的引用。即,ab都指向同一个列表。对b所做的任何更改也会影响a。这可以使用id函数进行验证。相同的id值表示两者都指向同一个对象。

>>> c = a[:]
>>> print(c)
[1, 8, 3, 4]
>>> id(a)
46734952
>>> id(c)
46563240  

在上述情况下,a的切片被分配给c。因此,制作副本并将其分配给c。因此ida的{​​{1}}值不同。

答案 1 :(得分:1)

因为有两种类型的数据

  1. 可变数据类型

    • list
    • 字典
    • 设置
  2. 不可变数据类型

    • 数字(布尔,整数,浮点数和复数)
    • 字符串
    • 元组
    • frozenset
  3. 当您更改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