返回顶部

Python--操作列表

Python--操作列表

一、遍历整个列表

你经常需要遍历列表的所有元素,对每个元素执行相同的操作。例如,在游戏中,可能需要将每个界面元素平移相同的距离;对于包含数字的列表,可能需要对每个元素执行相同的统计运算;在网站中,可能需要显示文章列表中的每个标题。需要对列表中的每个元素都执行相同的操作时,可使用python中的for循环。
假设我们有一个魔术师名单,需要将其中每个魔术师的名字都打印出来。为此,可以分别获取名单中的每个名字,但这种做法会导致多个问题。例如,如果名单很长,将包含大量重复的代码。另外,每当名单的长度发生变化时,都必须修改代码。通过使用for循环,可以让Python去处理这些问题。
下面使用for循环来打印魔术师名单中的所有名字:

首先,定义一个列表。接下来,定义一个for循环。这行代码让Python从列表magicians中取出一个名字,并将其与变量magician相关联。最后,让Python打印前面赋给变量magician的名字。这样,对于列表中的每个名字,Python都将重复执行循环操作。
你可以这样解读这些代码:对于列表magicians中的每位魔术师,都将其名字打印出来。

1. 深入研究循环

循环这种概念很重要,因为它是让计算机自动完成重复工作的常见方式之一。例如,在前面示例中使用的简单循环里,Python将首先读取其中的第一行代码:

这行代码让Python获取列表magicians中的第一个值“alice”,并将其与变量magician相关联。接下来,Python读取下一行代码:

它让Python打印magician的值,依然是“alice”。鉴于该列表还包含其他值,Python返回到循环的第一行:

Python获取列表中的下一个名字“david”,并将其与变量magician相关联,再执行下面这行代码:

Python再次打印变量magician的值,当前为“david”。接下来,Python再次执行整个循环,对列表中的最后一个值“carolina”进行处理。至此,列表中没有其他的值了,因此Python接着执行程序的下一行代码。在这个示例中,for循环后面没有其他代码,因此程序就此结束。
刚开始使用循环时请牢记,对列表中的每个元素,都将执行循环指定的步骤,而不管列表包含多少个元素。如果列表包含一百万个元素,Python就重复执行指定的步骤一百万次,且通常速度非常快。
另外,编写for循环时,可以给一次与列表中每个值相关联的临时变量指定任意名称。然而,选择描述单个列表元素的有意义名称大有裨益。然而,对于小猫列表、小狗列表和一般性列表,像下面这样编写for循环的第一行代码是不错的选择:

这些命名约定有助于你明白for循环中将对每个元素执行的操作。使用单数和复数式名称,可帮助你判断代码段处理的是单个列表元素还是整个列表。

2. 在for循环中执行更多操作

在for循环只能那个,可对每个元素执行任何操作。下面来扩展前面的示例,对于每位魔术师,都打印一条消息,指出他的表演太精彩了。

相对于前一个示例,唯一的不同是为每位魔术师打印了一条以名字为抬头的消息。这个循环第一次迭代时,变量magician的值为“alice”,因此Python打印的第一条消息的抬头为“Alice”;第二次迭代时,消息的抬头为“David”;第三次迭代时,抬头为“Carolina”。
输出表明,对于列表中的每位魔术师,都打印了一条个性化消息。

在for循环中,想包含多少行代码都可以。在代码行for magician in magicians后面,每个缩进的代码行都是循环的一部分,将针对列表中的每个值都执行一次。因此,可对列表中的每个值执行任意次数的操作。
下面再添加一行代码,告诉每位魔术师,我们期待他的下一次表演:

两个函数调用print()都缩进了,因此它们都将针对列表中的每位魔术师执行一次。第二个函数调用print()中的换行符“\n”在每次迭代结束后都插入一个空行,从而整洁地将针对各位魔术师的消息编组。

在for循环中,想包含多少行代码都可以。实际上,你会发现使用for循环对每个元素执行众多不同那个的操作很有用。

3. 在for循环结束后执行一些操作

for循环结束后怎么办呢?通常,你需要提供总结性输出或接着执行程序必须完成的其他任务。
在for循环后面,没有缩进的代码都只执行一次,不会重复执行。下面来打印一条向全体魔术师致谢的消息,感谢他们的精彩表演。想要在打印给各位魔术师的消息后面打印一条给全体魔术师的致谢消息,需要将相应的代码放在for循环后面,且不缩进:

你在前面看到了,开头两个函数调用print()针对列表中的每位魔术师重复执行。然而,第三个函数调用print()没有缩进,因此只执行一次。

使用for循环处理数据是一种对数据集执行整体操作的不错方式。例如,你可能使用for循环来初始化集成:遍历角色列表,将每个角色显示到屏幕上。然后在循环后面添加一个不缩进的代码块,在屏幕上绘制所有角色后显示一个Play Now按钮。

二、避免缩进错误

Python根据缩进来判断代码行与前一个代码行的关系。在前面的示例中,向各位魔术师显示消息的代码行是for循环的一部分,因为它们缩进了。Python通过使用缩进让代码更易读。简单地说,它要求你使用缩进让代码整洁而结构清晰。在较长的Python程序中,你讲看到缩进程度各不相同的代码块,从而对程序的组织结构有大致的认识。
开始编写必须正确缩进的代码时,需要注意一些常见的缩进错误。例如,程序员有时候会将不需要缩进的代码块缩进,而对于必须缩进的代码块却忘了缩进。查看这样的错误示例有助于你以后避开它们,以及在它们出现在程序中时进行修复。
下面来看一些较为常见的缩进错误。

1. 忘记缩进

对于位于for语句后面且属于循环组成部分的代码行,一定要缩进。如果忘记缩进,Python会提醒你:

函数调用print()应缩进却没有缩进。Python没有找到期望缩进的代码块时,会让你知道哪行代码有问题。
通常,将紧跟在for语句后面的代码行缩进,可消除这种缩进错误。

2. 忘记缩进额外的代码行

有时候,循环能够运行且不会报告错误,但结果可能出人意料。试图在循环中执行多项任务,却忘记缩进其中的一些代码行时,就会出现这种情况。
例如,如果忘记缩进循环中的第二行代码(它告诉每位魔术师,我们期待其下次表演),就会出现这种情况:

第二个函数调用print()原本需要缩进,但Python发现for语句后面有一行代码时缩进的,因此没有报告错误。最终的结果是,对于列表中的每位魔术师,都执行了第一个函数调用pring(),因为它缩进了;而第二个函数调用print()没有缩进,因此只在循环结束后执行一次。由于变量magician的终值为“carolina”,结果只有她收到了第二条消息。
这是一个逻辑错误。从语法上看,这些Python代码是合法的,但由于处在逻辑错误,结果并不符合预期。如果你预期某项操作将针对每个列表元素都执行一次,但它总共只执行了一次,请确定需要将一行还是多行代码缩进。

3. 不必要的缩进

如果你不小心缩进了无须缩进的代码行,Python将指出这一点:

函数调用print()无须缩进,因为它并非循环的组成部分。因此Python将指出这种错误。
为避免意外缩进错误,请只缩进需要缩进的代码。在前面编写的程序中,只有要在for循环中对每个元素执行的代码需要缩进。

4. 循环后不必要的缩进

如果不小心缩进了应在循环结束后执行的代码,这些代码将针对每个列表元素重复执行。在有些情况下,这可能导致Python报告语法错误,但在大多数情况下,这只会导致逻辑错误。
例如,如果不小心缩进了感谢全体魔术师精彩表演的代码行,结果将如何呢。

由于最后一条代码也进行了缩进,它将针对列表中的每位魔术师执行一次。
这也是一个逻辑错误,Python不知道你的本意,只要代码符合缩进语法,它就会运行。如果原本直营执行一次的操作执行了多次,可能要对执行该操作的代码取消缩进。

5. 遗漏了冒号

for语句末尾的冒号告诉Python,下一行是循环的第一行。

如果不小心遗漏了冒号,将导致语法错误,因为Python不知道你意欲何为。这种错误虽然易于消除,但并不那么容易发现。程序员为找出这样的单字符错误,花费的时间多得令人惊讶。此类错误之所以难以发现,是因为通常在人们的意料之外。

三、创建数值列表

需要存储一组数的原因有很多。例如,在游戏中,需要跟踪每个角色的位置,还可能需要跟踪玩家的几个最高得分;在数据可视化中,处理的几乎都是由数(如温度、距离、人口数量、经度和纬度等)组成的集合。
列表非常适合用于存储数字集合,而Python提供了很多工具,可帮助你高效地处理数字列表。明白如何有效地使用这些工具后,即便列表包含数百万个元素,你编写的代码也能运行得很好。

1. 使用函数range()

Python函数range()让你能够轻松地生成一系列数。例如,可以像下面这样使用函数range()来打印一系列数:

上述代码好像应该打印数1~5,但实际上不会打印5。
在这个示例中,range()只打印数1~4。这是编程语言中常见的差一行为的结果。函数range()让Python从指定的第一个值开始数,并在到达你指定的第二个值时停止。因为它在第二个值处停止,所以输出不包含该值(这里为5)。
要打印数1~5,需要使用range(1,6):

这样,输出将从1开始、到5结束。
使用range()时,如果输出不符合预期,请尝试将指定的值加1或者减1。
调用函数range()时,也可只指定一个参数,这样它将从0开始。例如,range(6)返回数0~5。

2. 使用range()创建数字列表

要创建数字列表,可使用函数list()将range()的结果直接转化为列表。如果将range()作为list()的参数,输出将是一个数字列表。
在前一节的示例中,只是将一系列数打印出来。要将这组数转换为列表,可使用list():

使用函数range()时,还可指定步长。为此,可给这个函数指定第三个参数,Python将根据这个步长来生成数。
例如,下面的代码打印1~10的偶数:

在这个示例中,函数range()从2开始数,然后不断加2,知道达到或超过终值(11)。
使用函数range()几乎能够创建任何需要的数集。例如,如何创建一个列表,其中包含前10个整数(1~10)的平方呢?在Python中,用两个星号(**)表示乘方运算。下面的代码演示了如何将前10个整数的平方加入一个列表中:

首先,创建一个名为squares的空列表,接下来,使用话术range()让Python遍历一遍1~10的值。在循环中,计算当前值的平方,并将结果赋给变量square。然后,将新计算得到的平方值附加到列表squares的末尾。最后,循环结束后,打印列表squares。

为了让代码更简洁,可不适用临时变量square,而直接将每个计算得到的值附加到列表末尾:

第三行的代码与上一个程序的第三行和第四行的代码等效。在循环中,计算每个值的平方,并立即将结果附加到列表squares的末尾。
创建更复杂的列表时,可使用上述两种方法中的任何一种。有时候,使用临时变量会让代码更易读;而在其他情况下,这样做只会让代码无谓地变长。你首先应该考虑的是,编写清晰易读且能完成所需功能的代码,等到审核代码时,再考虑采用更高效的方法。

3. 对数字列表执行简单的统计计算

有几个专门用于处理数字列表的Python函数。例如,你可以轻松地找出数字列表的最大值、最小值和总合:

注意:
考虑到版面,本节使用的数字列表都很短,但这里介绍的知识也适用于包含数百万个数的列表。

4. 列表解析

前面介绍的生成列表squares的方式包含三四行代码,而列表解析让你只需编写一行代码就能生成这样的列表。列表解析将for循环和创建新元素的代码合并成一行,并自动附加新元素。面向初学者的教程并非都会介绍列表解析,这里之所以介绍列表解析,是因为等你开始阅读他人编写的代码时,很可能会遇到它。
下面的示例使用列表解析创建你在前面看到的平方数列表:

要使用这种语法,首先指定一个描述性的列表名,如squares。然后,指定一个左方括号,并定义一个表达式,用于生成要存储到列表中的值。在这个示例中,表达式为value ** 2,它计算平方值。接下来,编写一个for循环,用于给表达式提供值,再加上右方括号。在这个示例中,for循环为for value in range(1, 11),它将值1~10提供给表达式value **。请注意,这里的for语句末尾没有冒号。
结果与前面的平方数列表相同。

要创建自己的列表解析,需要经过一定练习,但能够熟练地创建常规列表后,你会发现这样做是完全值得的。当你觉得编写三四行代码来生成列表有点繁复时,就应考虑创建列表解析了。

四、使用列表的一部分

在前面,你学习了如何访问单个列表元素。在本章张,你一直在学习如何处理列表的所有元素。你还可以处理列表的部分元素,Python称之为切片

1. 切片

要创建切片,可指定要使用的第一个元素和最后一个元素的索引。与函数range()一样,Python在到达第二个索引之前的元素后停止。要输出列表中的前三个元素,需要指定索引0和3,这将返回索引为0、1和2的元素。
下面的示例处理的是一个运动队成员列表:

代码打印该列表的一个切片,其中只包含三名队员。输出也是一个列表,其中包含前三名队员。

你可以生成列表的任意子集。例如,如果要提取列表的第二、第三和第四个元素,可将起始索引指定为1,并将终止索引指定为4:

此时,切片始于“martina”、终于“florence”。

如果没有指定第一个索引,Python将自动从列表开头开始:

由于没有指定起始索引,Python从列表开头开始提取。

要让切片终止于列表末尾,也可使用类似的语法。例如,如果要提取从第三个元素到列表末尾的所有元素,可将起始索引指定为2,并省略终止索引:

Python将返回从第三个元素到列表末尾的所有元素。

无论列表多长,这种语法都能够让你输出从特定位置到列表末尾的所有元素。前面说过,负数索引返回列表末尾相应距离的元素,因此你可以输出列表末尾的任意切片。例如,如果要输出名单上的最后三名队员,可使用切[-3:]:

上述代码打印最后三名队员的名字,即便队员名单长度发生变化,也依然如此。

注意:
可在表示切片的发个括号内指定第三个值。这个值告诉Python在指定范围内每隔多少元素提取一个。

2. 遍历切片

如果要遍历列表的部分元素,可在for循环中使用切片。下面的示例遍历前三名队员,并打印他们的名字:

这里没有遍历整个队员列表,而只遍历前三名队员。

在很多情况下,切片都很有用。例如,编写游戏时,你可以在玩家退出游戏时将其最终得分加入一个列表中,然后将该列表按降序排列以获取三个最高得分,再创建一个只包含前三个得分的切片;处理数据时,可使用切片来进行批量处理;编写Web应用程序时,可使用切片来分页显示信息,并在每页显示数量合适的信息。

3. 复制列表

我们经常需要根据既有列表创建全新的列表。下面来介绍复制列表的工作原理,以及复制列表可提供极大帮助的一种情形。
要复制列表,可创建一个包含整个列表的切片,方法是同时省略起始索引和终止索引[:]。这让Python创建一个始于第一个元素、终止于最后一个元素的切片,即整个列表的副本。
例如,假设有一个列表包含你最喜欢的四种食品,而你想再创建一个列表,并在其中包含一位朋友喜欢的所有食品。不过,你喜欢的食品,这位朋友也都喜欢,因此可通过复制来创建这个列表:

首先,创建一个你喜欢的食品列表,名为my_foods。然后创建一个名为friend_foods的新列表。在不指定任何索引的情况下从列表my_foods中提取一个切片,从而创建这个列表的副本,并将该副本赋给变量friend_foods。打印这两个列表后,我们发现其包含的食品相同。

为核实确实有两个列表,下面在每个列表中都添加一种食品。并核实每个列表都记录了相应人员喜欢的食品:

输出表明:
“cannoli”包含在你喜欢的食品列表中,而“ice cream”不在。
“ice cream”包含在你朋友细化的食品列表中,而“cannoli”不在。
如果只是将my_foods赋给friend_foods,就不能得到两个列表。例如,下面演示了在不使用切片的情况下复制列表的情况:

这里将my_foods赋给friend_foods,而不是将my_foods的副本赋给friend_foods。这种语法实际上是让Python将新变量friend_foods关联到已与my_friends相关联的列表,因此这两个变量指向同一个列表。有鉴于此,当我们将“cannoli”添加到my_foods中时,它也将出现在friend_foods中。同样,虽然“ice cream”好像只被加入到了friend_foods中,但它也将出现在这两个列表中。
输出表明,两个列表是相同的,这并非我们想要的结果。
注意:
暂时不要考虑这个示例中的细节。当试图使用列表的副本时结果出乎意料,基本上都要确认你是否像前面的示例那样使用切片复制了列表。

五、元组

列表非常适合用于存储在程序运行期间可能变化的数据集。列表时可以修改的,这对处理网站的用户列表或游戏中的角色列表至关重要。然而,有时候你需要创建一系列不可修改的元素,元组可以满足这种需求。Python将不能修改的值称为不可变的,而不可变的列表被称为元组

1. 定义元组

元组看起来很像列表,但使用圆括号而非中括号来标识,定义元组后,就可使用索引来访问其元素,就像访问列表元素一样。
例如,如果有一个大小不应改变的矩形,可将其长度和宽度存储在一个元组中,从而确保它们是不能修改的:

首先定义元组dimensions,为此使用了圆括号而不是方括号。接下来,分别打印该元组的各个元素,使用的语法与访问列表元素时使用的语法相同。

下面来尝试修改元组dimensions的一个元素,看看结果如何:

上图代码试图修改第一个元素的值,导致Python返回类型错误消息。由于试图修改元组的操作是被禁止的,因此Python指出不能给元组的元素复制。
这很好,因为我们希望Python在代码试图修改举行的尺寸时引发错误。
注意:
严格地说,元组时由逗号标识的,圆括号只是让元组看起来更整洁、更清晰。如果你要定义只包含一个元素的元组,必须在这个元素后面加上逗号:

创建只包含一个元素的元组通常没有意义,但自动生成的元组有可能只有一个元素。

2. 遍历元组中的所有值

像列表一样,也可以使用for循环来遍历元组中的所有值:

就像遍历列表时一样,Python返回元组中所有的元素。

3. 修改元组变量

虽然不能修改元组的元素,但可以给存储元组的变量赋值。因此,如果要修改前述矩形的尺寸,可重新定义整个元组:

首先定义一个元组,并将其存储的尺寸打印出来。接下来,将一个新元组关联到变量dimensions。然后,打印新的尺寸。这次,Python不会引发任何错误,因为给元组变量重新赋值是合法的。

相比于列表,元组是更简单的数据结构。如果需要存储的一组值在程序的整个生命周期内都不变,就可以使用元组。

六、设置代码格式

随着你编写的程序越来越长,有必要了解一些代码格式设置约定。请花时间让你的代码尽可能易于阅读。这有助于你掌握程序是做什么的,也可以帮助他人理解你编写的代码。
为确保所有人编写的代码结构都大致一致,Python程序员会遵循一些格式设置约定。学会编写整洁的Python后,就能明白他人编写的Python代码的整体结构——只要他们和你遵循相同的指南。要成为专门程序员,应从现在开始就遵循这些指南,以养成良好的习惯。

1. 格式设置指南

要提出Python语言修改建议,需要编写Python改进提案(Python Enhancement Proposal,PEP)。PEP8是最古老的PER之一,向Python程序员提供了代码格式设置指南。PEP8的篇幅很长,但基本上与复杂的编码结构相关。
Python格式设置指南的编写者深知,代码被阅读的次数比编写的次数多。代码编写出来后,调试时需要阅读;给程序添加新功能时,需要花很长的时间阅读;与其他程序员分享代码时,这些程序员也会阅读。
如果一定要在让代码易于编写和易于阅读之间做出选择,Python程序员几乎总是选择后者。下面的指南可帮助你从一开始就编写出清晰的代码。

2. 缩进

PEP8 建议每级缩进都使用4个空格。这既可以提高可读性,又留下了足够的多级缩进空间。
在字处理文档中,大家常常使用制表符而不是空格进行缩进。对于字处理文档来说,这样做的效果很好,但混合使用制表符和空格会让Python解释器感到迷惑。每款文本编辑器都提供了一种设置,可将你输入的制表符转换为指定数量的空格。你在编写代码时绝对应该使用制表符键,但一定要对编辑器进行设置,使其在文档中插入空格而不是制表符。
在程序中混合使用制表符和空格可能导致极难排查的问题。如果混合使用了制表符混合空格,可将文件中的所有制表符都转换为空格,大多数编辑器都提供了这样的功能。

3. 行长

很多Python程序员建议每行不超过80字符。最初指定这样的指南时,在大多数计算机中,终端窗口每行只能容纳79个字符。当前,计算机屏幕每行可容纳的字符数多得多,为何还要使用79字符的标准行长呢?这里有别的原因。专业程序员通常会在同一个屏幕上打开多个文件,使用标准行长可以让他们在屏幕上并排打开两三个文件时同时看到各个文件的完整行。PEP8还建议注释的行长不应超过72字符,因为有些工具为大型项目自动生成文档时,会在每行注释开头添加格式化字符。
PEP8中有关行长的指南并非不可逾越的红线,有些小组将最大行长设置为99字符。在学习期间,你不用过多考虑代码的行长,但别忘了,写作编写程序时,大家几乎都遵守PEP8指南。在大多数编辑器中,可以设置一个视觉标志(通常时一条竖线),让你知道不能越过的界线在什么地方。

4. 空行

要将程序的不同部分分开,可使用空行。你应该使用空行来组织程序文件,但也不能滥用。只要按照示例展示的那样做,就能掌握其中的平衡。例如,如果你有五行创建列表的代码,还有三行处理该列表的代码,那么用一个空行将这两部分隔开是合适的。然而,你不应该使用三四个空行将其隔开。
空行不会影响代码的运行,但会影响代码的可读性。Python解释器根据水平缩进情况来解读代码,但不关心垂直间距。

5. 其他格式设置指南

PEP8还有很多其他的格式设置建议,但这些指南针对的程序大多比目前为止学习的程序要复杂的多,暂时不表。

posted @ 2021-12-20 14:39  丨君丶陌  阅读(233)  评论(0编辑  收藏  举报