python疑难问题---5、二维列表初始化
一、总结
一句话总结:
可以用c = [[0]*4 for _ in range(3)]的方式来初始化3行4列的二维数组,用乘号(*)重复不可变数据类型(这里是int 0),用循环重复可变数据类型(这里是列表)
1、b = [[0] * 4] * 3 初始化3行4列 二维数组不可行的实质?
列表在用乘号(*)重复的时候,重复的列表的地址是一样的,而python中的列表是可变数据类型,地址一样,代表指向的是同一个列表,当然会一变全变,也就是b[0][0]变的时候,b[1][0]和b[2][0]都会跟着变
二、二维列表初始化
博客对应课程的视频位置:5、二维列表初始化
https://www.fanrenyi.com/video/32/306
一、分析
当我们使用python处理数据的时候,经常会遇到需要初始化一个二维列表,然后对列表的每一个子项目(我们这里假设也是列表)进行操作。
列表的乘号(*)操作可以重复元素,比如
In [16]:
print(['Hi!'] * 4)
所以我们考虑用 *号 来初始化列表
In [17]:
a = [0] * 5
print(a)
In [18]:
print(id(a[0]))
print(id(a[1]))
print(id(a[2]))
print(id(a[3]))
print(id(a[4]))
In [19]:
a[1]=1
a[3]=7
print(a)
In [20]:
print(id(a[0]))
print(id(a[1]))
print(id(a[2]))
print(id(a[3]))
print(id(a[4]))
普通初始化的列表
In [21]:
aa = [0,0,0,0,0]
print(id(aa[0]))
print(id(aa[1]))
print(id(aa[2]))
print(id(aa[3]))
print(id(aa[4]))
In [22]:
aa[1] = 11
aa[2] = 22
print(aa)
In [23]:
print(id(aa[0]))
print(id(aa[1]))
print(id(aa[2]))
print(id(aa[3]))
print(id(aa[4]))
我们可以根据这种思路快速初始化二维列表
二、有坑的方式
In [24]:
b = [[0] * 4] * 3
print(b)
这样的确非常快的初始化了一个列表,但是这样有一个很大的问题
In [25]:
b[0][0] = "这个方法不行"
print(b)
我们可以看到,我们本来是希望将 "这个方法不行" 赋值给b[0][0],结果发现b[i][0]的值都是 "这个方法不行" 了
为什么会这样呢?
我们来看这个式子:b = [[0] 4] 3中的后面这个3,将前面的列表重复了3次,我们重复之后,得到的子列表的地址是一样,
而python中列表是可变数据类型(也就是列表里面数据变的时候,地址不会变,值相同的两个列表,地址也是不一样的,如果两个列表地址是一样的,代表的是同一个列表),既然代表的是同样一个列表,那么一个变,其它跟着变,也很好解释了
b = [[0] 4] 3 初始化3行4列 二维数组不可行的实质
列表在用乘号(*)重复的时候,重复的列表的地址是一样的,而python中的列表是可变数据类型,地址一样,代表指向的是同一个列表,当然会一变全变,也就是b[0][0]变的时候,b[1][0]和b[2][0]都会跟着变 </font>
In [26]:
print(id(b[0]))
print(id(b[1]))
print(id(b[2]))
我们来看一下正常方式初始化的列表
我们来看一下正常方式初始化的列表,对应的二维列表中的一维列表的地址肯定是不一样的,地址不一样,操作肯定互不影响
In [27]:
bb = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
print(id(bb[0]))
print(id(bb[1]))
print(id(bb[2]))
In [28]:
bb[0][0] = 1
bb[2][2] = 5
print(bb)
三、正确的方式
可以用c = [[0] * 4 for _ in range(3)]的方式来初始化3行4列的二维数组,用乘号(*)重复不可变数据类型(这里是int 0),用循环重复可变数据类型(这里是列表)
In [31]:
c = [[0] * 4 for _ in range(3)]
c[0][0]='这个方法行'
print(c)
In [32]:
print(id(c[0]))
print(id(c[1]))
print(id(c[2]))
In [ ]: