Python数据结构学习笔记
上QQ阅读APP看书,第一时间看更新

3.1 使用列表

在Python程序中,列表也称序列,是Python语言中最基本的一种数据结构,和其他编程语言(C/C++/Java)中的数组类似。序列中的每个元素都分配一个数字,这个数字表示这个元素的位置或索引,第一个索引是0,第二个索引是1,依此类推。

↑扫码看视频(本节视频课程时间:10分05秒)

3.1.1 列表的基本用法

在Python程序中使用中括号“[]”来表示列表,并用逗号来分隔其中的元素。例如,下面的代码创建一个简单的列表。

在上述代码中,创建一个名为“car”的列表,在列表中存储了4个元素,执行后会将列表打印输出,执行效果如图3-1所示。

图3-1 执行效果

(1)创建数字列表

在Python程序中,可以使用方法range()创建数字列表。在下面的实例文件num.py中,使用方法range()创建一个包含3个数字的列表。

在上述代码中,一定要注意方法range()的结尾参数是4,才能创建3个列表元素。执行效果如图3-2所示。

图3-2 执行效果

(2)访问列表中的值

在Python程序中,因为列表是一个有序集合,所以要想访问列表中的任何元素,只需将该元素的位置或索引告诉Python即可。要想访问列表元素,可以指出列表的名称,再指出元素的索引,并将其放在方括号内。例如,下面的代码可以从列表car中提取第一款汽车:

上述代码演示了访问列表元素的语法。当发出获取列表中某个元素的请求时,Python只会返回该元素,而不包括方括号和引号,上述代码执行后只会输出:

开发者还可以通过方法title()获取任何列表元素,获取元素“audi”的代码如下:

上述代码执行后的输出结果与前面的代码相同,只是首字母a变为大写,上述代码执行后只会输出:

在Python程序中,字符串还可以通过序号(序号从0开始)来取出其中的某个字符,例如'abcde.[1]'取得的值是'b'。

再看下面的实例文件fang.py,功能是访问并显示列表中元素的值。

在上述代码中,分别定义了两个列表list1和list2,执行效果如图3-3所示。

图3-3 执行效果

在Python程序中,第一个列表元素的索引为0,而不是1。在大多数编程语言中的数组也是如此,这与列表操作的底层实现相关。自然而然地,第二个列表元素的索引为1。根据这种简单的计数方式,要访问列表的任何元素,都可将其位置减1,并将结果作为索引。例如要访问列表中的第4个元素,可使用索引3实现。在下面的代码中,演示了显示列表中第2个和第4个元素的方法。

执行后输出:

3.1.2 实战演练——删除列表中的重复元素并保持顺序不变

在Python程序中,可以删除列表中重复出现的元素,并且保持剩下元素的显示顺序不变。如果序列中保存的元素是可哈希的,那么上述功能可以使用集合和生成器实现。在下面的实例文件delshun.py中,演示了在可哈希情况下的实现过程。在本实例中预先设置了一个列表a,然后通过for循环遍历里面的数据。

如果一个对象是可哈希的,那么在它的生存期内必须是不可变的,这需要有一个__hash__()方法。在Python程序中,整数、浮点数、字符串和元组都是不可变的。在上述代码中,函数dedupe()实现了可哈希情况下的删除重复元素功能,并且保持剩下元素的显示顺序不变。执行后的效果如图3-4所示。

图3-4 执行效果

上述实例文件delshun.py有一个缺陷,只有当序列中的元素是可哈希时才能这么做。如果想在不可哈希的对象序列中去除重复项,并保持与按顺序不变应如何实现呢?下面的实例文件buhaxi.py中,演示了上述功能的实现过程。

在上述代码中,函数buha()中参数key的功能是设置一个函数将序列中的元素转换为可哈希的类型,这样做的目的是为了检测重复选项。执行效果如图3-5所示。

图3-5 执行效果

3.1.3 实战演练——找出列表中出现次数最多的元素

在Python程序中,如果想找出列表中出现次数最多的元素,可以考虑使用collections模块中的Counter类,调用该类中的函数most_common()来实现。在下面的实例文件most.py中,演示了使用函数most_common()找出列表中出现次数最多的元素的过程。

在上述代码中预先定义了一个列表words,在里面保存了一系列的英文单词,使用函数most_common()找出哪些单词出现的次数最多。执行后的效果如图3-6所示。

图3-6 执行效果

3.1.4 实战演练——排序类定义的实例

在Python程序中,可以排序一个类定义的多个实例。使用内置函数sorted()可以接受一个用来传递可调用对象(callable)的参数key,而这个可调用对象会返回待排序对象中的某些值;sorted()函数则利用这些值来比较对象。假设在程序中存在多个User对象的实例,如果想通过属性user_id来对这些实例进行排序,则可以提供一个可调用对象将User实例作为输入,然后返回user_id。在下面的实例文件leishili.py中,演示了排序上述User对象实例的过程。

在上述代码中,在①处使用lambda表达式进行了处理,在②处使用内置函数operator.attrgetter()进行了处理。执行效果如图3-7所示。

图3-7 执行效果

3.1.5 实战演练——使用列表推导式

在Python程序中,列表推导式(List Comprehension)是一种简化代码的优美方法。Python官方文档描述道:列表推导式提供了一种创建列表的简洁方法。列表推导能够非常简洁地构造一个新列表,只需用一条简洁的表达式即可对得到的元素进行转换变形。使用Python列表推导式的语法格式如下:

参数说明如下:

●out_exp_res:列表生成元素表达式,可以是有返回值的函数;

●for out_exp in input_list:迭代input_list将out_exp传入out_exp_res表达式中;

●if out_exp==2:根据条件可以过滤哪些值。

例如,想创建一个包含从1到10的平方的列表,在下面的实例文件chuantong.py中使用range()函数创建了包含10个数字的列表,分别演示了传统方法和列表推导式方法的实现过程。

在上述代码中,①~②通过传统方式实现,③和之后的代码通过列表推导式方法实现。执行后将会输出:

再假如想输出30内能够整除3的整数,使用传统方法的实现代码如下:

而通过列表推导式方法的实现代码如下:

上述两种方式执行后都会输出:

再看下面的代码,首先获取30内能够整除3的整数,然后依次输出获得整数的平方。

执行后会输出:

在下面的实例文件shaixuan.py中,使用列表推导式筛选了列表中mylist中大于零和小于零的数据。

通过上述代码,分别筛选出列表mylist中大于零和小于零的元素,执行效果如图3-8所示。

图3-8 执行效果

在Python程序中,有时候筛选的标准无法简单地表示在列表推导式或生成器表达式中,假设筛选过程涉及异常处理或者其他一些复杂的细节。此时可以考虑将处理筛选功能的代码放到单独的功能函数中,然后使用内建的filter()函数进行处理。下面的实例文件dandu.py演示了这一功能。在本实例中,创建了一个包含多个字符元素的列表values。

在上述代码中,因为使用函数filter()创建了一个迭代器,所以如果想要得到一个列表形式的结果,请确保在filter()前面加上list()函数。执行后会输出:

3.1.6 实战演练——命名切片

在Python程序中,有时会发现编写的代码变得杂乱无章而无法阅读,到处都是硬编码的切片索引,此时需要想将它们清理干净。如果代码中存在过多硬编码的索引值,将会降低代码的可读性和可维护性。很多开发者都有这样的经验,几年以后再回过头看自己以前编写的代码,会发现自己当初编写这些代码是多么的幼稚而不合理。

在Python程序中,使用函数slice()可以实现切片对象,能够在切片操作函数中实现参数传递功能,可以被用在任何允许进行切片操作的地方。使用函数slice()的语法格式如下。

参数说明如下:

●start:起始位置;

●stop:结束位置;

●step:间距。

下面的实例文件qie.py演示了使用函数slice()实现切片操作的过程。

在上述代码中,slice对象实例s可以分别通过属性s.start、s.stop和s.step来获取该对象的信息。在①中,使用indices(size)函数将切片映射到特定大小的序列上,这将会返回一个(start,stop,step)元组,所有的值都已经正好限制在边界以内,这样当进行索引操作时可以避免出现IndexError异常。执行后的效果如图3-9所示。

图3-9 执行效果