lst = [0] * 5
print(lst)
for i in range(len(lst)):
lst[i] = i
print(lst)
先来看一段代码,对于存储基本数据类型的列表,有时候会这样进行初始化,这样做完全是没有问题的,先后打印的结果是
[0, 0, 0, 0, 0]
[0, 1, 2, 3, 4]
对于这个列表,完全正常的初始化和赋值了,但是假如想定义嵌套列表,这样做会不会出问题呢?接下来看下面的代码.
lst = [[0, 0, 0]] * 5
print(lst)
lst[0][0] = 1
print(lst)
它的输出结果是这样的:
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
从打印结果可以发现,明明只给第一个列表里的第一个元素赋值为1,但是为什么所有列表里的第一个元素都变成了1呢?我们可以大胆猜测,会不会是因为它们用了同一个对象?我们可以用内置函数id( )来验证一下.
lst = [[0, 0, 0]] * 5
for i in range(5):
print(id(lst[i]))
打印的结果是这样的:
2903677295040
2903677295040
2903677295040
2903677295040
2903677295040
它们用的确实是同一个对象.至于为什么会这样,是因为 * 是复制的对象的引用,通俗的说也就是地址值.
所以哪怕不是嵌套列表,初始化之后它们的地址值也是一样的,大家可以自行验证,这也就是为什么我们修改了其中一个列表,其他的也会修改,因为它们使用的是同一个对象.那么怎么正确的创建一个嵌套列表呢?没错,使用列表推导式.
lst = [[0, 0, 0] for _ in range(5)]
for i in range(5):
print(id(lst[i]))
2326353097024
2326353099264
2326353328832
2326354411392
2326354399360
这样创建出来的对象地址都不同,那么我们修改其中的任意一个,自然也不会影响到其他的元素了.
评论区