In [1]: a = [1, 2]
In [2]: a.extend([3, 4])
In [3]: a
Out[3]: [1, 2, 3, 4]
In [4]: a += [3, 4]
In [5]: a
Out[5]: [1, 2, 3, 4, 3, 4]
In [6]: a = a + [6, 7]
In [7]: a
Out[7]: [1, 2, 3, 4, 3, 4, 6, 7]
In [1]: a = [1, 2]
In [2]: id(a)
Out[2]: 1576442566792
In [3]: a.extend([3, 4])
In [4]: id(a)
Out[4]: 1576442566792
In [5]: a += [5, 6]
In [6]: a
Out[6]: [1, 2, 3, 4, 5, 6]
In [7]: id(a)
Out[7]: 1576442566792
In [8]: a = a + [7, 8]
In [9]: id(a)
Out[9]: 1576444319688
我们都知道元组是不可变对象,不能对其进行修改,但如果元组内部存放了列表这种可变类型数据,是可以被修改的。
来看一下以下代码
例如:
In [10]: t = (1, 2, [3, 4])
In [11]: t[2].extend([5, 6])
In [12]: t
Out[12]: (1, 2, [3, 4, 5, 6])
In [13]: t[2] += [7, 8]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-76b157051dad> in <module>
----> 1 t[2] += [7, 8]
TypeError: 'tuple' object does not support item assignment
In [14]: t[2]
Out[14]: [3, 4, 5, 6, 7, 8]
In [15]: t[2] = t[2] + [9, 10]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-15-61694a39f991> in <module>
----> 1 t[2] = t[2] + [9, 10]
TypeError: 'tuple' object does not support item assignment
In [16]: t[2]
Out[16]: [3, 4, 5, 6, 7, 8]
是不是很奇怪?
extend能直接修改元组里的列表
+=虽然会报错,但是元组里的列表又被修改了
而=则是既报错,元组里的列表也没被修改
看看三种修改对应的内存操作:
元组中存放的是对象的引用,元组的不可变,指的是不可以修改对象的引用(意思就是下图的三个箭头是不能被修改的)。而元组中存放的数据,如果是可变类型,是可以被修改的。
1、t[2].extend([5, 6]),直接找到列表[3, 4]存放的内存地址,把 5和6直接添加进去,不修改箭头指向;
2、t[2] += [5, 6],直接找到列表[3, 4]存放的内存地址,把5和6直接添加进去,并且重新覆盖修改箭头的指向,这个过程中,添加数据不会报错,修改指向会报错,所以最后的修改是失败的,但我们能看到内存存放的数据暂时是有被修改了;
3、t[2] = t[2] + [5, 6],是直接找到[3, 4]存放的内存地址,把里面存放的数据复制一遍,加上 5, 6 ,再存到另一个位置,接着修改指向,所以第二步修改指向的时候会报错,并且原来[3, 4]存放的数据还是不变的。