微信扫一扫打赏支持

python疑难问题---5、二维列表初始化

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)
['Hi!', 'Hi!', 'Hi!', 'Hi!']

所以我们考虑用 *号 来初始化列表

In [17]:
a = [0] * 5
print(a)
[0, 0, 0, 0, 0]
In [18]:
print(id(a[0]))
print(id(a[1]))
print(id(a[2]))
print(id(a[3]))
print(id(a[4]))
140724000563568
140724000563568
140724000563568
140724000563568
140724000563568
In [19]:
a[1]=1
a[3]=7
print(a)
[0, 1, 0, 7, 0]
In [20]:
print(id(a[0]))
print(id(a[1]))
print(id(a[2]))
print(id(a[3]))
print(id(a[4]))
140724000563568
140724000563600
140724000563568
140724000563792
140724000563568

普通初始化的列表

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]))
140724000563568
140724000563568
140724000563568
140724000563568
140724000563568
In [22]:
aa[1] = 11
aa[2] = 22
print(aa)
[0, 11, 22, 0, 0]
In [23]:
print(id(aa[0]))
print(id(aa[1]))
print(id(aa[2]))
print(id(aa[3]))
print(id(aa[4]))
140724000563568
140724000563920
140724000564272
140724000563568
140724000563568

我们可以根据这种思路快速初始化二维列表

二、有坑的方式

In [24]:
b = [[0] * 4] * 3
print(b)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

这样的确非常快的初始化了一个列表,但是这样有一个很大的问题

In [25]:
b[0][0] = "这个方法不行"
print(b)
[['这个方法不行', 0, 0, 0], ['这个方法不行', 0, 0, 0], ['这个方法不行', 0, 0, 0]]

我们可以看到,我们本来是希望将 "这个方法不行" 赋值给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]))
1728181289928
1728181289928
1728181289928

我们来看一下正常方式初始化的列表

我们来看一下正常方式初始化的列表,对应的二维列表中的一维列表的地址肯定是不一样的,地址不一样,操作肯定互不影响

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]))
1728183167816
1728183168136
1728183168008
In [28]:
bb[0][0] = 1
bb[2][2] = 5
print(bb)
[[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 5, 0]]

三、正确的方式

可以用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)
[['这个方法行', 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
In [32]:
print(id(c[0]))
print(id(c[1]))
print(id(c[2]))
1728183168200
1728183189704
1728183189640
In [ ]:
 
 
系列博客对应课程视频地址:
1、遍历列表的三种方式-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/293
2、字典排序-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/294
3、可变和不可变数据类型-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/295
4、python文件处理-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/305
5、二维列表初始化-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/306
6、python中浅拷贝和深度拷贝-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/307
7、python中的with...as...-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/320
8、只有一个数的元组表示-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/343
9、Python类中call函数的作用-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/361
10、python遍历字典的几种方式-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/368
11、python内嵌for...in循环-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/369
12、python生成器-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/370
13、Python切片操作-范仁义-读书编程笔记
https://www.fanrenyi.com/video/32/377
 
 
posted @ 2020-07-02 04:36  范仁义  阅读(388)  评论(0)    收藏  举报