机器学习入门:Python语言实现
上QQ阅读APP看书,第一时间看更新

3.1 列表

Python支持列表数据类型,以及丰富的列表相关功能。由于列表不需要统一数据类型,所以你可以创建不同数据类型的列表,以及多维列表。接下来的几节将展示如何在Python中操作列表结构。

3.1.1 列表和基本操作

Python列表由一对方括号括起来的逗号分隔值(comma-separated value)组成。以下示例说明了在Python中定义列表的语法,以及如何对Python列表执行各种操作:

057-01

你可以将多个变量分配给一个列表,前提是变量的数量和类型要与列表结构匹配。举个例子:

058-01

以下示例说明了如何在更复杂的数据结构中给变量赋值:

058-02

如果要获取上述代码块中date1元素的年/月/日组成部分,可进行如下操作:

058-03

如果变量的数量和/或结构与数据不匹配,则会显示一条错误消息,如下所示:

058-04

如果指定的变量数少于数据的项数,你将看到一条错误消息,如下所示:

059-01

1. 反转和排序列表

Python的reverse()方法可反转列表的内容,如下所示:

059-02

Python的sort()方法可对列表进行排序:

059-03

你可以对列表进行排序,然后反转其内容,如下所示:

059-04

另一种反转列表的方法如下所示:

059-05

需要牢记的是,reversed(array)是可迭代的,而且它并不是列表。但以下代码片段可以将一个反转的数组转换为列表:

059-06

清单3.1包含一个while循环,其逻辑与前面介绍的列表相反:如果num可被多个数字整除(每个数字都严格小于num),则num不是素数。

清单3.1 Uppercase1.py

059-07

清单3.1的输出如下所示:

060-01

排序的数字列表中,第一个数字是最小值。如果反转排序列表,则第一个数字是最大值。以下代码说明了有很多方法可以反转列表:

060-02

上述代码块的输出如下所示:

060-03

第二种(更好的)方法对列表进行排序:

060-04

第三种列表排序方法涉及sort()方法的内置函数:

060-05

当你不想修改列表的原始顺序,或者想在一行上编写多个列表操作时,上述代码非常有用。

2. 过滤列表

Python可以过滤一个列表(也称作列表解析),如下所示:

060-06

你也可以在过滤器中指定if/else逻辑,如下所示:

060-07

上述代码块的输出如下所示:

060-08

3. 数字和字符串的排序列表

清单3.2的Sorted1.py脚本用于判断两个列表是否为排序列表。

清单3.2 Sorted1.py

061-01

清单3.2首先对列表list1list2进行初始化,并分别基于列表list1list2生成排序列表sort1sort2。如果list1等于sort1,则list1已被排序;同样,如果list2等于sort2,则list2已被排序。

清单3.2的输出如下所示:

061-02

请注意,如果对字符串列表进行排序,输出结果是区分大小写的,大写字母出现在小写字母之前。这是因为ASCII的核对顺序把大写字母(十进制65到十进制91)放在小写字母(十进制97到十进制127)之前。下例示例可具体解释说明:

061-03

你还可以设定反转选项,用反向的顺序对列表进行排序:

061-04

你甚至可以根据列表中每一项的长度对列表进行排序:

061-05

如果想要在排序操作中将大写字母视为小写字母,可以设定str.lower,如下所示:

061-06

4. Python中的冒泡排序

前面的示例说明了如何使用sort()函数对数字列表进行排序。但有时需要在Python中实现其他类型的排序。清单3.3的BubbleSort.py说明了如何在Python中实现冒泡排序。

清单3.3 BubbleSort.py

062-01

清单3.3的输出结果如下所示:

062-02

3.1.2 列表中的表达式

以下构造类似for循环,但这个循环末尾没有冒号“:”字符:

062-03

3.1.3 连接字符串列表

Python提供了join()方法来连接文本字符串,如下所示:

062-04

有很多方法可以连接一组字符串,然后打印结果。下面这种是效率最低的方法:

062-05

以下两种都是更佳的方法:

063-01

3.1.4 Python中的range()函数

本节你将了解Python中可用于遍历列表的range()函数,如下所示:

063-02

你可以使用for循环遍历字符串列表,如下所示:

063-03

你可以使用for循环遍历字符串列表,并显示更多详细信息,如下所示:

063-04

上面的输出结果显示列表x中每个字符串的长度,后跟字符串文本内容。

对数字、大写和小写字母计数

清单3.4的CountCharTypes.py脚本对字符串中数字和字母进行计数。

清单3.4 Counter1.py

063-05

清单3.4初始化了与计数器相关的变量,后跟一个循环(其中循环变量设为i),从0迭代到字符串str1的长度。用字符串str1索引i位置上的字母来初始化变量char。循环的下一部分使用条件逻辑来确定char是数字还是字母字符。在后一种情况下(即字母字符时),代码会检查字符是大写还是小写。但不论怎样,相应的计数器变量的值都会增加。

清单3.4的输出结果如下所示:

064-01

3.1.5 数组和append()函数

Python有一个数组类型(import array),本质上是一个异构列表。但是除了略微节省内存使用之外,该数组类型与列表类型相比没有任何优势。你也可以定义异构数组:

064-02

你可以将新元素追加至一个列表中:

064-03

你可以将简单的变量赋值给列表中的元素,如下所示:

064-04

上述代码的输出如下所示:

065-01

Python中split()函数比前面的示例更便捷(尤其是在元素数未知或可变的情况下),你将在下一节看到split()函数的示例。

3.1.6 使用列表和split()函数

你可以使用Python的split()函数拆分文本字符串中的单词,并用这些单词填充一个列表,示例如下:

065-02

打印文本字符串中单词列表的一个简易方法如下所示:

065-03

你可以按以下方法搜索字符串中的单词:

065-04

3.1.7 对列表中的单词计数

Python提供了Counter类,可以对列表中的单词进行计数。清单3.5的CountWord2.py说明了如何计算出现频率最高的前三个单词。

清单3.5 CountWord2.py

065-05

清单3.5用一组字符初始化mywords变量,然后将mywords作为参数传递给Counter来初始化word_counts变量。topThree变量是一个数组,包含了mywords中的三个出现次数最多的字符(及其出现的次数)。清单3.5的输出如下:

066-01

3.1.8 遍历成对的列表

Python支持成对的列表操作,这意味着可以执行类似于向量的操作。以下代码片段将每个列表元素乘以3:

066-02

创建一个新列表,包含原始元素,以及原始元素乘以3的值:

066-03

计算两个列表中每对数字的乘积:

066-04

计算两个列表中每对数字的总和:

066-05

计算两个列表的每对元素的乘积:

066-06

3.1.9 其他与列表相关的函数

Python还提供了其他与列表相关的函数,例如append()insert()delete()pop()extend()。Python中也支持index()count()sort()reverse()函数。以下代码块说明了这些函数。

定义一个Python列表(允许数字重复):

066-07

显示1和2的出现次数:

067-01

在位置3处插入-8:

067-02

从例表中删除3:

067-03

从例表中删除1:

067-04

将19添加至列表:

067-05

打印列表中19的索引:

067-06

对列表进行反转:

067-07

对列表进行排序:

067-08

用列表b扩展列表a

067-09

从列表中删除第一个2:

067-10

删除列表的最后一项:

068-01

现在你已经了解与列表相关的操作,下一节将介绍如何将Python列表用作栈。

3.1.10 栈和队列

栈是一种LIFO(Last In First Out,后进先出)的数据结构,其具有push()pop()函数,分别用于添加和删除元素。栈中最新添加的元素位于顶部,因此是被删除的第一个元素。

以下代码说明了如何在Python中创建栈,以及从栈中删除和添加元素。创建一个Python列表(我们将其用作栈):

068-02

将5添加到栈:

068-03

从栈中删除最后一个元素:

068-04

队列是FIFO(First In First Out,先进先出)的数据结构,其具有insert()pop()函数,分别用于插入和删除元素。队列中最新添加的元素位于顶部,因此是被删除的最后一个元素。将新元素添加到已满的队列时,会删除队列中最早的元素。

以下代码说明了如何在Python中创建队列,以及如何将元素插入和追加到队列中。

创建一个Python列表(我们将其用作队列):

068-05

在队列的开头插入5:

068-06

从队列中删除最后一个元素:

068-07

上面的代码使用q.insert(0,5)在开头插入元素,并使用q.pop()从末端删除元素。但要牢记的是,Python中insert()操作很慢,如果在位置0执行插入,需要将基础数组中的所有元素向下复制一个位置。因此可以将collections.dequecoll.appendleft()coll.pop()一起使用,其中collCollection类的代表。

前面,你已经学习了如何利用Python列表来模拟队列。但是Python中也有一个队列对象。以下代码片段说明了如何在Python中使用队列。

069-01

下一节将介绍如何在Python中处理向量。

3.1.11 使用向量

向量是一维的数组,基于向量的操作包括加、减、内积等。清单3.6的MyVectors.py说明了如何执行基于向量的操作。

清单3.6 MyVectors.py

069-02

清单3.6首先定义三个列表,每个列表代表一个向量。列表d1s1分别表示v3v2之差、v3v2之和。p1代表v3v2的“内积”(也称为“点积”)。清单3.6的输出如下:

069-03

3.1.12 使用矩阵

二维矩阵即为二维数组中的值,因此创建一个矩阵是非常方便的。举个例子,下面的代码块说明了如何获得二维矩阵中的元素:

070-01

上述代码的输出结果如下:

070-02

清单3.7的My2DMatrix.py说明了如何创建和填充二维矩阵。

清单3.7 My2DMatrix.py

070-03

清单3.7首先初始化两个变量rowscols,然后用rows x cols得到矩阵my2DMatrix,其初始值为0。清单3.7的下一部分包含一个嵌套循环,把位置为(row,col)的my2DMatrix元素赋值为row*row+col*col。清单3.7中的最后一行代码打印了my2DArray的内容。清单3.7的输出如下:

070-04

3.1.13 使用NumPy库处理矩阵

NumPy库(可以通过pip安装)支持矩阵对象,可以处理Python中的矩阵。以下示例说明了NumPy的一些特性。

初始化矩阵m,然后显示其内容:

071-01

下面的代码片段返回矩阵m的转置:

071-02

下面的代码片段返回矩阵m的逆(如果存在):

071-03

下面的代码片段定义向量y,然后计算乘积m*v

071-04

下面的代码片段导入numpy.linalg子包,然后计算矩阵m的行列式:

071-05

下面的代码片段查找矩阵m的特征值:

071-06

下面的代码片段查找方程m*x=v的解:

071-07

除了上述示例之外,NumPy包还提供了其他功能,你可以在网上搜索相关文章和教程来了解这些功能。