目录
- 1. 序幕
- 2. 前期回顾
- 3. 创建一个二维列表
- 4. 二维列表的宏观层面
- 4.1. 二维列表的值
- 4.2. 二维列表的数据类型
- 4.3. 二维列表的长度
- 5. 二维列表的微观层面
- 5.1. 二维列表元素的值
- 5.2. 二维列表元素的数据类型
- 5.3. 二维列表元素的索引
- 6. 二维列表的遍历
- 6.1. 单层循环遍历
- 6.2. 双层循环遍历
- 7. 练习题
1. 序幕
上一次给大家分享了关于一维列表的一些有趣的东西,今天要为大家带来的是二维列表,一维列表的plus版!
在开始介绍我们的新玩具之前,我们先回顾一下一维列表的一些知识吧~
2. 前期回顾
对一维列表的解剖学考究,分为两个层面——宏观层面和微观层面,或者说整体层面和局部层面。从宏观层面上来看,我们关心三个点:数据类型、值、长度。
一维列表的简称是列表,全称是一维列表类型变量。在实践上常常以这样的形式出现:
nums = [20, 24, 11, 8, 20, 52]
nums
首先本质上是一个变量,那么关于变量我们会关心这么两个方面:一、变量的数据类型是什么?二、变量的值是什么?
变量的数据类型,我们有一个工具可以用来操作,那就是type()
函数;而关于变量的值,我们常常使用print()
函数输出在控制台上以查看它。而nums
这个变量呢,它不是旁的什么,它是列表(类型的变量)。那么继而我们引发出更深的兴趣点——它有几个元素,即它的长度是多少?对此,我们可以使用len()
函数来获取列表的长度。
# 列表(列表型变量)的宏观操作
print(nums) # 输出变量的值
print(type(nums)) # 输出变量的数据类型
print(len(nums)) # 输出列表的长度
说完宏观层面,我们再来说说微观层面。因为列表是由元素组成的,所以微观层面我们关注的就是元素。元素呢,也有三方面的考量:一、元素的值是什么?二、元素的索引是多少?三、元素的数据类型是什么?
print(nums[0]) # 输出第1个元素的值
print(nums.index(20)) # 输出值为20的元素的索引
print(type(nums[0])) # 输出第1个元素的数据类型
- 列表
- 宏观层面
- 值
- 数据类型
- 列表长度
- 微观层面
- 元素的值
- 元素的索引
- 元素的数据类型
- 宏观层面
3. 创建一个二维列表
废话不多说,直奔我们今天的主题吧——二维列表。
二维列表在数学上,或者数据分析与机器学习领域,又称为矩阵或向量组。上一次我们讲一维列表时,提到一维列表也叫做向量。Tips:在理解一维列表与二维列表的关系时,用向量-向量组这个视角会非常方便。
在创建一个二维列表变量时,我们一般习惯上使用下面这样的形式:
nums = [
[20, 24, 11, 8, 20, 52],
[20, 24, 11, 8, 22, 28],
[50, 47, 10, 14, 11, 4],
]
这种形式的目的在于,凸显其二维的特点!当然我们也可以写成一行,但是不建议这么做。
nums = [[20, 24, 11, 8, 20, 52], [20, 24, 11, 8, 22, 28], [50, 47, 10, 14, 11, 4]]
不知道,聪明的你是否留意到,写成一行后,有一个细微的差别。那就是最后一个元素后面没有逗号了。其实两种写法,最后一个元素后面都可以有或者没有。那为什么要有这种区别呢?答案很简单,为了美观😄
4. 二维列表的宏观层面
4.1. 二维列表的值
二维列表首先也是一个变量,那么同样的我们也先从宏观层次来考量一下它的三个方面吧——值、类型、长度。
print(nums) # 输出变量nums的值
你将会在控制台上获得如下内容:
[[20, 24, 11, 8, 20, 52], [20, 24, 11, 8, 22, 28], [50, 47, 10, 14, 11, 4]]
ps:无论你使用哪种形式创建一个二维列表,都将获得以上内容。
看完了变量nums
的值,接下来,我们再看看变量nums
的类型吧。
4.2. 二维列表的数据类型
print(type(nums)) # 输出变量nums的数据类型
结果是:
<class 'list'>
意思是,“数据类型是列表”。看到这里,好奇的你不知道是否会感到狐疑——“一维列表是列表,二维列表也是列表,敢情都是列表,还分啥一维列表、二维列表呢?一维列表和二维列表的区别是什么呢?”答案是,区别在值上。
最后,我们看看宏观维度上,在长度这个方面,二维列表又会有怎样的表现呢?
4.3. 二维列表的长度
print(len(nums)) # 获取列表nums的长度
接下来发生的事情,可能会更让你大惊失色。实验运行结果出来了,控制台上赫然输出了一行“大字”——
3
“什么?一个二维列表欸,写了那么多字才创建好的一个二维列表诶!咋长度才为3啊?这还没有,一开始创建的那个一维列表的长度长呢?”那么,问题来了,为什么会这样呢?首先让我们回顾一下,“列表长度”的定义——“列表中元素的个数”。而列表由元素组成,元素之间由逗号隔开。好的,现在重新审视一下我们的二维列表nums
,你看看,哪里会与3
有关呢?
nums = [
[20, 24, 11, 8, 20, 52],
[20, 24, 11, 8, 22, 28],
[50, 47, 10, 14, 11, 4],
]
显然,这里有3行一维列表。没错!这3行一维列表就是我们二维列表nums
中的元素,一共有3个元素。刚开始提到的一维列表nums = [20, 24, 11, 8, 20, 52]
中,每个元素都是整数int
型。而现在这个二维列表中的元素呢,每个都是列表list
型。仅此而已。列表中套列表,我们就称它为二维列表。而这里,类比于数学上的向量-向量组,就很好理解了。[20, 24, 11, 8, 20, 52],[20, 24, 11, 8, 22, 28],[50, 47, 10, 14, 11, 4]三个行向量,组成了一个向量组。考虑到,这次聊的是基础语法,面对的朋友呢,可能大多数是没有学过线性代数的,就不过多提及了。感兴趣的朋友可以自己探索,悄悄给你透露一下,线性代数对于机器学习至关重要!
5. 二维列表的微观层面
5.1. 二维列表元素的值
言归正传,二维列表也是列表,只是每一个元素都是一维列表罢了。那么对于一维列表行之有效的方法,对于现在的二维列表也依然有效。比如使用下标访问法,获取元素的值。
print(nums[0]) # 获取第一个元素的值
控制台上的结果为:
[20, 24, 11, 8, 20, 52]
不知道,看到这样的结果,你会有什么想法?nums[0]
是一个列表……
这有一个一维列表num
,你还记得怎么访问它的第一个元素吗?
num = [20, 24, 11, 8, 20, 52]
对的。
print(num[0])
那么现在告诉你,nums[0]
是个一维列表,我们把它赋值给num
。我们该如何访问列表型变量num
的第一个元素呢,答案还是num[0]
。
num = nums[0]
print(num[0])
我颠来倒去,一点一点地往前推理,不知道你是否产生了一个大胆的想法。那就是——
print(nums[0][0])
是的!没错!我们可以直接使用nums[0][0]
,来访问二维列表nums
中第一个元素[20, 24, 11, 8, 20, 52]
中的第一个元素20
。用二维列表相应的专门术语来说,称之为访问二维列表中第一行第一列元素。
方才,我们探索出了,使用下标访问法访问二维列表某行某列的元素(其实这个讲法不太好,这是用数学里矩阵的概念来理解的,后面的操作会让你发现这个讲法有点和其他概念不融洽,不过没关系,我们暂且遵守传统的表述习惯)。以上是关于,元素的值的操作。那么接下来我们研究一下对于元素的类型的操作。
5.2. 二维列表元素的数据类型
print(type(nums[0])) # 获取第一个元素的数据类型
运行结果是:
<class 'list'>
对于这个结果,我们不意外,之前分析元素的值的时候,我们已经单凭肉眼就可以一眼判断出数据类型了。🆗,就像前面访问元素的值一样,我们也可以获取某行某列某个元素的数据类型。
print(type(nums[0][0])) # 获取第一个行向量中的第一个元素的数据类型
ps:注意我的注释,这里使用的是向量组的相关概念。使用向量-向量组的概念来梳理二维列表可以解决前面提到的理论体系不融洽的问题。另外,由于二维列表的构成方式,只能由行向量组成,所以其实这里“行向量”可以简写为“向量”。
本次样例的运行结果是:
<class 'int'>
还记得微观层面的三个部分是哪些吗?我们眼下还差哪部分没提到呢?对了,index()
!
5.3. 二维列表元素的索引
在一维列表nums
中,index()
的用法及运行效果是这样的:
nums = [20, 24, 11, 8, 20, 52]
print(nums.index(20))
结果为:
0
那直接照搬这个用法,到二维列表呢?
nums = [
[20, 24, 11, 8, 20, 52],
[20, 24, 11, 8, 22, 28],
[50, 47, 10, 14, 11, 4],
]
print(nums.index(20))
你会得到一个报错ValueError
,值错误。错误详情是,“20不在列表中”。
ValueError Traceback (most recent call last)
Cell In[9], line 1
----> 1 print(nums.index(20))
ValueError: 20 is not in list
来,问你哈。你觉得“20”在不在二维列表nums
中?怎么不在?肉眼可见的在呀!“20”不光在二维列表中,而且有三个“20”呢!
那,这样子就大错特错了。前面分析过,二维列表nums
的数据类型为list
,列表的长度为3
,其中每一个元素都是list
型的。“20”不在二维列表中,准确来讲是,“20”作为元素的值不在二维列表中。“20”是作为二维列表元素的元素的值存在的。类比于欧洲中世纪封建等级制度就是——“附庸的附庸,不是我的附庸——二维列表元素的元素,不是二维列表的元素。虽然听起来很拗口,但是用代码表达起来很简单,你照下面这样写就可以得到一个正常输出:
print(nums[0].index(20))
它将输出,“20”在列表[20, 24, 11, 8, 20, 52]
中第一次出现的位置。
6. 二维列表的遍历
走过千山万水,经历过种种考验,总算来到这第九九八十一难——遍历!什么是遍历呢?遍历就是,按照一定的次序,依次访问数据中所有的内容。对于一维列表,我们一般按照从左往右的阅读顺序访问列表的元素。而对于二维列表,我们一般按照从上往下、从左往右的顺序遍历。ps:当然你也可以说是按照从左往右的顺序😉(创建二维列表时,第二种写法,揭露了二维列表在计算机内存上存储的本质形式——线性)。
6.1. 单层循环遍历
二维列表也是列表,我们完全可以像一维列表一样,使用一层循环即可遍历二维列表中的元素(每个元素都是列表)。在一维列表中,我们详细介绍了四种遍历写法,这里就不再赘述了。仅以for循环为例,写在下面:
# 下标访问法遍历二维列表
for i in range(len(nums)):
print(nums[i])
运行结果为:
[20, 24, 11, 8, 20, 52]
[20, 24, 11, 8, 22, 28]
[50, 47, 10, 14, 11, 4]
使用迭代器遍历法会更加简洁一些,我们可以优化如下:
for num in nums:
print(num)
6.2. 双层循环遍历
一维列表到上面的遍历就结束了,但是看到遍历的结果,程序员们似乎不太满足。(我想大概是受到古老的C语言的影响——C语言不支持直接输出一行“列表”,或者用C语言的讲法“一行数组”。)好吧,既然打开二维列表之后,里面还有一层列表,就像俄罗斯套娃一样。那么让我们不胜其烦地再进行一层循环吧~
# 双层for循环遍历二维列表,下标访问法
for i in range(len(nums)):
for j in range(len(nums[i])):
print(nums[i][j])
# 双层for循环遍历二维列表,迭代器法
for num in nums:
for n in num:
print(n)
whie循环的套娃式写法我就不再提了,另外你不光可以写纯for的双层循环,或者纯while的双层循环,你还可以写又for又while的双层循环。外层有4种循环写法,内层也有4种循环写法,根据乘法原理,一共可以得到
4
×
4
=
16
4\times4=16
4×4=16种写法。
我们把目光就放到双层for循环上,我们先看看上面的代码段运行的效果吧。两段代码的运行效果都一样:
20
24
11
8
20
52
20
24
11
8
22
28
50
47
10
14
11
4
这个形式,检查起来,也太……麻烦了吧😅咱们能不能让它可以一眼就看得过来呢?目前是由于行数太多了,得往下翻翻才能看完。那我们能不能让它输出的行数变少呢?分析一下代码,我们发现我们使用的是print(nums[i][j])
,print()
函数没有设置end
参数的值,默认是\n
换行(print(n)
同理)。那么我们可以这样改造一下:
# 双层for循环遍历二维列表,下标访问法
for i in range(len(nums)):
for j in range(len(nums[i])):
print(nums[i][j], end=' ')
这次是没有很多行了……
20 24 11 8 20 52 20 24 11 8 22 28 50 47 10 14 11 4
直接变成一行输出了。分不清是从一维列表里遍历出的结果,还是从二维列表里遍历出的结果,并且如果数据量再大点,不用竖着翻了,还是得横着翻的。那么能不能有种办法,既可以少输出几行,又能体现出二维列表的特征呢?诶~~~方法是有滴!方法总比问题多,“提出你的需求,编程总可以满足你”!
# 双层for循环遍历二维列表,下标访问法
for i in range(len(nums)):
for j in range(len(nums[i])):
print(nums[i][j], end=' ')
print()
这一次的结果是这样的:
20 24 11 8 20 52
20 24 11 8 22 28
50 47 10 14 11 4
怎么样?是不是很完美!古人云,“世间安有两全法”。诶~~~~不好意思,有才就是任性😁。
7. 练习题
上一次我们留了一道题,说好这一次讲的。我们现在把参考答案公布如下:
total = 0
for elem in a_list:
total += elem
print(total / len(a_list))
接下来,我们给出这次的练习题吧,请听题:
Question:
统计前面用到的二维列表nums中有多少个数字
答案可以写在评论区哦,期待下一次与你们再见,see u~