系列文章目录
《Python编程从入门到实践》 第一部分 基础知识
第3章 列表简介
第4章 操作列表
文章目录
一、列表是什么?
列表由一系列按特定顺序排列的元素组成。可以将任何东西加入列表中,其中的元素之间可以没有任何关系。
在Python中,用方括号([])来表示列表,并用逗号来分隔其中的元素:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles)
['trek', 'cannondale', 'redline', 'specialized']
1.访问列表元素
列表是有序集合,因此要访问列表的任何元素,只需将该元素的位置或索引告诉Python即可:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0])
trek
你还可以对任何列表元素调用的字符串方法。例如,可使用方法title()让元素’trek’的格式更整洁:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[0].title())
Trek
2.索引从0 而不是1 开始
在Python中,第一个列表元素的索引为0,而不是1。下面的代码访问索引1和3处的自行车:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[1])
print(bicycles[3])
cannondale
specialized
Python为访问最后一个列表元素提供了一种特殊语法。通过将索引指定为 -1,可让Python返
回最后一个列表元素:
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
print(bicycles[-1])
specialized
这种语法很有用,因为你经常需要在不知道列表长度的情况下访问最后的元素。这种约定也适用于其他负数索引,例如,索引-2返回倒数第二个列表元素,索引-3返回倒数第三个列表元素,以此类推。
3.使用列表中的各个值
可像使用其他变量一样使用列表中的各个值。
bicycles = ['trek', 'cannondale', 'redline', 'specialized']
message = "My first bicycle was a " + bicycles[0].title() + "."
print(message)
My first bicycle was a Trek.
二、修改、添加和删除元素
1.修改列表元素
修改列表元素的语法与访问列表元素的语法类似。要修改列表元素,可指定列表名和要修改的元素的索引,再指定该元素的新值。
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles[0] = 'ducati'
print(motorcycles)
['honda', 'yamaha', 'suzuki']
['ducati', 'yamaha', 'suzuki']
2.在列表中添加元素
1. 在列表末尾添加元素
方法append() 将元素’ducati’添加到了列表末尾,而不影响列表中的其他所有元素:
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
motorcycles.append('ducati')
print(motorcycles)
['honda', 'yamaha', 'suzuki']
['honda', 'yamaha', 'suzuki', 'ducati']
方法append()让动态地创建列表易如反掌,例如,你可以先创建一个空列表,再使用一系列的append()语句添加元素。下面来创建一个空列表,再在其中添加素’honda’、‘yamaha’和’suzuki’:
motorcycles = [] #创建一个空列表
motorcycles.append('honda')
motorcycles.append('yamaha')
motorcycles.append('suzuki')
print(motorcycles)
['honda', 'yamaha', 'suzuki']
这种创建列表的方式极其常见,因为经常要等程序运行后,你才知道用户要在程序中存储哪些数据。为控制用户,可首先创建一个空列表,用于存储用户将要输入的值,然后将用户提供的每个新值附加到列表中。
2. 在列表中插入元素
使用方法insert() 可在列表的任何位置添加新元素。为此,你需要指定新元素的索引和值。
motorcycles = ['honda', 'yamaha', 'suzuki']
motorcycles.insert(0, 'ducati')
print(motorcycles)
在这个示例中,值’ducati’被插入到了列表开头;方法insert()在索引0处添加空间,并将值’ducati’存储到这个地方。这种操作将列表中既有的每个元素都右移一个位置:
['ducati', 'honda', 'yamaha', 'suzuki']
3.从列表中删除元素
可以根据位置或值来删除列表中的元素。
1. 使用del语句删除元素
如果知道要删除的元素在列表中的位置,可使用del语句。使用del可删除任何位置处的列表元素,条件是知道其索引。
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
del motorcycles[0]
print(motorcycles)
['honda', 'yamaha', 'suzuki']
['yamaha', 'suzuki']
2. 使用方法pop()删除元素
有时候,你要将元素从列表中删除,并接着使用它的值。例如,在游戏中,你可能需要获取刚被射杀的外星人的x和y坐标,以便在相应的位置显示爆炸效果;
方法pop() 可删除列表末尾的元素,并让你能够接着使用它。术语弹出(pop)源自这样的类比:列表就像一个栈,而删除列表末尾的元素相当于弹出栈顶元素。
motorcycles = ['honda', 'yamaha', 'suzuki']
print(motorcycles)
popped_motorcycle = motorcycles.pop()
print(motorcycles)
print(popped_motorcycle)
['honda', 'yamaha', 'suzuki']
['honda', 'yamaha']
suzuki
**我们从这个列表中弹出一个值,并将其存储到变量popped_motorcycle中。**然后我们打印这个列表,以核实从其中删除了一个值。最后,我们打印弹出的值,以证明我们依然能够访问被删除的值。
输出表明,列表末尾的值’suzuki’已删除,它现在存储在变量popped_motorcycle中。
方法pop()还能有什么使用场景?假设列表中的摩托车是按购买时间存储的,就可使用方法pop()打印一条消息,指出最后购买的是哪款摩托车。
3. 弹出列表中任何位置处的元素
实际上,你可以使用pop()来删除列表中任何位置的元素,只需在括号中指定要删除的元素的索引即可。
motorcycles = ['honda', 'yamaha', 'suzuki']
first_owned = motorcycles.pop(0)
print('The first motorcycle I owned was a ' + first_owned.title() + '.')
The first motorcycle I owned was a Honda.
别忘了,每当你使用pop()时,被弹出的元素就不再在列表中了。
如果你不确定该使用del语句还是pop()方法,下面是一个简单的判断标准:如果你要从列表中删除一个元素,且不再以任何方式使用它,就使用del语句;如果你要在删除元素后还能继续使用它,就使用方法pop()。
4. 根据值删除元素
有时候,你不知道要从列表中删除的值所处的位置。如果你只知道要删除的元素的值,可使用方法remove()。
例如,假设我们要从列表motorcycles中删除值’ducati’:
motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati']
print(motorcycles)
motorcycles.remove('ducati')
print(motorcycles)
['honda', 'yamaha', 'suzuki', 'ducati']
['honda', 'yamaha', 'suzuki']
使用remove()从列表中删除元素时,也可接着使用它的值。下面删除值’ducati’,并打印一条消息,指出要将其从列表中删除的原因:
motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati']
print(motorcycles)
too_expensive = 'ducati'
motorcycles.remove(too_expensive)
print(motorcycles)
print(too_expensive.title() + " too expensive")
值’ducati’已经从列表中删除,但它还存储在变量too_expensive中,让我们能够打印一条消息,指出将’ducati’从列表motorcycles中删除的原因:
['honda', 'yamaha', 'suzuki', 'ducati']
['honda', 'yamaha', 'suzuki']
A Ducati too expensive
注意 方法remove()只删除第一个指定的值。如果要删除的值可能在列表中出现多次,就需要使用循环来判断是否删除了所有这样的值。
三、组织列表
1.使用方法sort()对列表进行永久性排序
Python方法sort() 让你能够较为轻松地对列表进行排序。假设你有一个汽车列表,并要让其中的汽车按字母顺序排列。
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort()
print(cars)
方法sort()永久性地修改了列表元素的排列顺序。现在,汽车是按字母顺序排列的,再也无法恢复到原来的排列顺序:
['audi', 'bmw', 'subaru', 'toyota']
你还可以按与字母顺序相反的顺序排列列表元素,为此,只需向sort()方法传递参数reverse=True。下面的示例将汽车列表按与字母顺序相反的顺序排列:
cars = ['bmw', 'audi', 'toyota', 'subaru']
cars.sort(reverse=True)
print(cars)
['toyota', 'subaru', 'bmw', 'audi']
2.使用函数sorted()对列表进行临时排序
要保留列表元素原来的排列顺序,同时以特定的顺序呈现它们,可使用函数sorted()。
cars = ['bmw', 'audi', 'toyota', 'subaru']
print("Here is the original list:")
print(cars)
print("\nHere is the sorted list:")
print(sorted(cars))
print("\nHere is the original list again:")
print(cars)
Here is the original list:
['bmw', 'audi', 'toyota', 'subaru']
Here is the sorted list:
['audi', 'bmw', 'subaru', 'toyota']
Here is the original list again:
['bmw', 'audi', 'toyota', 'subaru']
注意,调用函数sorted()后,列表元素的排列顺序并没有变。如果你要按与字母顺序相反的顺序显示列表,也可向函数sorted()传递参数reverse=True。
注意:
- 不能直接将方法sort()直接打印!
当直接使用sort()方法并输出时,结果是“None”
cars = ['bmw', 'audi', 'toyota', 'subaru']
print(cars.sort())
- 注意:并非所有的值都是小写的时候,按字母的排列顺序列表要复杂些。
3.倒着打印列表
要反转列表元素的排列顺序,可使用方法reverse():
cars = ['bmw', 'audi', 'toyota', 'subaru']
print(cars)
cars.reverse()
print(cars)
注意,reverse()不是指按与字母顺序相反的顺序排列列表元素,而只是反转列表元素的排列顺序:
['bmw', 'audi', 'toyota', 'subaru']
['subaru', 'toyota', 'audi', 'bmw']
方法reverse()永久性地修改列表元素的排列顺序,但可随时恢复到原来的排列顺序,为此只需对列表再次调用reverse()即可。
4.确定列表的长度
使用函数==len()==可快速获悉列表的长度。在下面的示例中,列表包含4个元素,因此其长度为4:
>>> cars = ['bmw', 'audi', 'toyota', 'subaru']
>>> len(cars)
4
在你需要完成如下任务时,len()很有用:确定还有多少个外星人未被射杀,需要管理多少项可视化数据,网站有多少注册用户等。
5.使用列表时避免索引错误
发生索引错误却找不到解决办法时,请尝试将列表或其长度打印出来。列表可能与你以为的截然不同,在程序对其进行了动态处理时尤其如此。
四、操作列表
操作列表中的每个元素,即遍历整个列表,这只需要几行代码,无论列表有多长。循环让你能够对列表的每个元素都采取一个或一系列相同的措施。
1.for循环遍历整个列表
使用Python中的for循环,让Python从列表magicians中取出一个名字,并将其存储在变量magician中。最后,我们让Python打印前面存储到变量magician中的名字:
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician)
alice
david
carolina
编写for循环时,对于用于存储列表中每个值的临时变量(在这里是magician),可指定任何名称。
使用单数和复数式名称,可帮助你判断代码段处理的是单个列表元素还是整个列表。这些命名约定有助于你明白for循环中将对每个元素执行的操作。
2.缩进
若想要在for 循环中执行更多的操作,则需要缩进。
下面的代码中两条print语句都缩进了,因此它们都将针对列表中的每位魔术师执行一次。
在for循环后面,没有缩进的代码都只执行一次,而不会重复执行。
magicians = ['alice', 'david', 'carolina']
for magician in magicians:
print(magician.title() + ", that was a great trick!")
print("I can't wait to see your next trick, " + magician.title() + ".\n")
print("Thank you, everyone. That was a great magic show!")
Alice, that was a great trick!
I can't wait to see your next trick, Alice.
David, that was a great trick!
I can't wait to see your next trick, David.
Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.
Thank you, everyone. That was a great magic show!
Python根据缩进来判断代码行与前一个代码行的关系。在前面的示例中,向各位魔术师显示消息的代码行是for循环的一部分,因为它们缩进了。Python通过使用缩进让代码更易读;简单地说,它要求你使用缩进让代码整洁而结构清晰。
3.创建数字列表
存储一组数字。
- 使用函数range()
Python函数range()让你能够轻松地生成一系列的数字。在这个示例中,range()只是打印数字1~4,这是你在编程语言中经常看到的差一行为的结果。
函数range()让Python从你指定的第一个值开始数,并在到达你指定的第二个值后停止,因此输出不包含第二个值(这里为5)。
要打印数字1~5,需要使用range(1,6)。使用range()时,如果输出不符合预期,请尝试将指定的值加1或减1。
for value in range(1,5):
print(value)
1
2
3
4
- 使用range()创建数字列表
要创建数字列表,可使用函数list() 将range()的结果直接转换为列表。如果将range()作为list()的参数,输出将为一个数字列表。在前一节的示例中,我们打印了一系列数字。要将这些数字转换为一个列表,可使用list():
numbers = list(range(1,6))
print(numbers)
[1, 2, 3, 4, 5]
使用函数range()时,还可指定步长。例如,下面的代码打印1~10内的偶数:
even_numbers = list(range(2,11,2))
print(even_numbers)
在这个示例中,函数range()从2开始数,然后不断地加2,直到达到或超过终值(11),因此输出如下:
[2, 4, 6, 8, 10]
使用函数range()几乎能够创建任何需要的数字集,例如,如何创建一个列表,其中包含前10个整数(即1~10)的平方呢?在Python中,两个星号(**)表示乘方运算。下面的代码演示了
如何将前10个整数的平方加入到一个列表中:
squares = [] #创建一个空列表
for value in range(1,11): #使用函数range()遍历1~10的值
square = value**2 #计算当前值的平方并将结果存储到变量square中
squares.append(square) #将新计算得到的平方值附加到列表squares末尾
print(squares) #打印列表squares
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
为让这些代码更简洁,可不使用临时变量square,而直接将每个计算得到的值附加到列表末尾:
squares = []
for value in range(1,11):
squares.append(value**2)
print(squares)
创建更复杂的列表时,可使用上述两种方法中的任何一种。有时候,使用临时变量会让代码更易读;而在其他情况下,这样做只会让代码无谓地变长。你首先应该考虑的是,编写清晰易懂且能完成所需功能的代码;等到审核代码时,再考虑采用更高效的方法。
- 列表解析
前面介绍的生成列表squares的方式包含三四行代码,而列表解析让你只需编写一行代码就能生成这样的列表。列表解析将for循环和创建新元素的代码合并成一行,并自动附加新元素。下面的示例使用列表解析创建你在前面看到的平方数列表:
squares = [value**2 for value in range(1,11)]
print(squares)
要使用这种语法,首先指定一个描述性的列表名,如squares;然后,指定一个左方括号,并定义一个表达式,用于生成你要存储到列表中的值。在这个示例中,表达式为value ** 2,它计算平方值。接下来,编写一个for循环,用于给表达式提供值,再加上右方括号。在这个示例中for循环为for value in range(1,11),它将值1~10提供给表达式value ** 2。
请注意,这里的for语句末尾没有冒号。
结果与你在前面看到的平方数列表相同:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
当你觉得编写三四行代码来生成列表有点繁复时,就应考虑创建列表解析了。
4.对数字列表执行简单的统计计算
有几个专门用于处理数字列表的Python函数。例如,你可以轻松地找出数字列表的最大值max()、最小值min() 和总和sum():
>>> digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> min(digits)
0
>>> max(digits)
9
>>> sum(digits)
45
5.使用列表的一部分(切片 遍历切片 复制列表)
以处理列表的部分元素——Python称之为切片
- 切片
要创建切片,可指定要使用的第一个元素和最后一个元素的索引。与函数range()一样,Python在到达你指定的第二个索引前面的元素后停止。要输出列表中的前三个元素,需要指定索引0~3,这将输出分别为0、1和2的元素。
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[0:3])
其中只包含三名队员。输出也是一个列表,其中包含前三名队员:
['charles', 'martina', 'michael']
你可以生成列表的任何子集,例如,如果你要提取列表的第2~4个元素,可将起始索引指定为1,并将终止索引指定为4:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[1:4])
这一次,切片始于’marita’,终于’florence’:
['martina', 'michael', 'florence']
如果你没有指定第一个索引,Python将自动从列表开头开始:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[:4])
['charles', 'martina', 'michael', 'florence']
要让切片终止于列表末尾,也可使用类似的语法。例如,如果要提取从第3个元素到列表末尾的所有元素,可将起始索引指定为2,并省略终止索引:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[2:])
Python将返回从第3个元素到列表末尾的所有元素:
['michael', 'florence', 'eli']
负数索引返回离列表末尾相应距离的元素,因此你可以输出列表末尾的任何切片。例如,如果你要输出名单上的最后三名队员,可使用切片players[-3:]:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print(players[-3:])
上述代码打印最后三名队员的名字,即便队员名单的长度发生变化,也依然如此。
- 遍历切片
如果要遍历列表的部分元素,可在for循环中使用切片。在下面的示例中,我们遍历前三名队员,并打印他们的名字:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
print("Here are the first three players on my team:")
for player in players[:3]:
print(player.title())
只遍历前三名队员:
Here are the first three players on my team:
Charles
Martina
Michael
在很多情况下,切片都很有用。例如,编写游戏时,你可以在玩家退出游戏时将其最终得分加入到一个列表中。然后,为获取该玩家的三个最高得分,你可以将该列表按降序排列,再创建一个只包含前三个得分的切片。
处理数据时,可使用切片来进行批量处理;
编写Web应用程序时,可使用切片来分页显示信息,并在每页显示数量合适的信息。
- 复制列表
你经常需要根据既有列表创建全新的列表。要复制列表,可创建一个包含整个列表的切片,方法是同时省略起始索引和终止索引([:])。这让Python创建一个始于第一个元素,终止于最后一个元素的切片,即复制整个列表。
例如,假设有一个列表,其中包含你最喜欢的四种食品,而你还想创建另一个列表,在其中包含一位朋友喜欢的所有食品。不过,你喜欢的食品,这位朋友都喜欢,因此你可以通过复制来创建这个列表:
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
print("My favorite foods are:")
print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)
My favorite foods are:
['pizza', 'falafel', 'carrot cake']
My friend's favorite foods are:
['pizza', 'falafel', 'carrot cake']
为核实我们确实有两个列表,下面在每个列表中都添加一种食品,并核实每个列表都记录了相应人员喜欢的食品:
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
my_foods.append('cannoli') #分别添加一种食物
friend_foods.append('ice cream')
print("My favorite foods are:")
print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)
My favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli']
My friend's favorite foods are:
['pizza', 'falafel', 'carrot cake', 'ice cream']
倘若我们只是简单地将my_foods赋给friend_foods,就不能得到两个列表。例如,下例演示了在不使用切片的情况下复制列表的情况:
my_foods = ['pizza', 'falafel', 'carrot cake']
#这行不通
friend_foods = my_foods
my_foods.append('cannoli')
friend_foods.append('ice cream')
print("My favorite foods are:")
print(my_foods)
print("\nMy friend's favorite foods are:")
print(friend_foods)
这里将my_foods赋给friend_foods,而不是将my_foods的副本存储到friend_foods。
这种语法实际上是让Python将新变量friend_foods关联到包含在my_foods中的列表,因此这两个变量都指向同一个列表。鉴于此,当我们将’cannoli’添加到my_foods中时,它也将出现在friend_foods中;同样,虽然’ice cream’好像只被加入到了friend_foods中,但它也将出现在这两个列表中。
输出表明,两个列表是相同的,这并非我们想要的结果:
My favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']
My friend's favorite foods are:
['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']
6.元组
列表非常适合用于存储在程序运行期间可能变化的数据集。列表是可以修改的,这对处理网站的用户列表或游戏中的角色列表至关重要。然而,有时候你需要创建一系列不可修改的元素,元组可以满足这种需求。Python将不能修改的值称为不可变的,而不可变的列表被称为元组。
元组看起来犹如列表,但使用圆括号而不是方括号来标识。定义元组后,就可以使用索引来访问其元素,就像访问列表元素一样。
例如,如果有一个大小不应改变的矩形,可将其长度和宽度存储在一个元组中,从而确保它们是不能修改的:
dimensions = (200, 50) #定义元组dimensions,使用圆括号而不是方括号
print(dimensions[0])
print(dimensions[1])
200
50
下面来尝试修改元组dimensions中的一个元素,看看结果如何:
dimensions = (200, 50)
dimensions[0] = 250
代码试图修改矩形的尺寸时,Python报告错误。返回类型错误消息。由于试图修改元组的操作是被禁止的,因此Python指出不能给元组的元素赋值。
- 遍历元组中的所有值
像列表一样,也可以使用for循环来遍历元组中的所有值:
dimensions = (200, 50)
for dimension in dimensions:
print(dimension)
200
50
- 修改元组变量
虽然不能修改元组的元素,但可以给存储元组的变量赋值。 因此,如果要修改前述矩形的尺寸,可重新定义整个元组:
dimensions = (200, 50)
print("Original dimensions:")
for dimension in dimensions:
print(dimension)
dimensions = (400, 100) #将一个新元组存储到变量dimensions中
print("\nModified dimensions:") #打印新的尺寸
for dimension in dimensions:
print(dimension)
这次,Python不会报告任何错误,因为给元组变量赋值是合法的:
Original dimensions:
200
50
Modified dimensions:
400
100
相比于列表,元组是更简单的数据结构。如果需要存储的一组值在程序的整个生命周期内都不变,可使用元组。
五、设置代码格式
随着你编写的程序越来越长,有必要了解一些代码格式设置约定。为确保所有人编写的代码的结构都大致一致,Python程序员都遵循一些格式设置约定。
格式设置指南:。PEP 8是最古老的PEP之一,它向Python程序员提供了代码格式设置指南。(Python Enhancement Proposal)
1.缩进
PEP 8建议每级缩进都使用四个空格,这既可提高可读性,又留下了足够的多级缩进空间。
在字处理文档中,大家常常使用制表符而不是空格来缩进。对于字处理文档来说,这样做的效果很好,但混合使用制表符和空格会让Python解释器感到迷惑。每款文本编辑器都提供了一种设置,可将输入的制表符转换为指定数量的空格。你在编写代码时应该使用制表符键,但一定要对编辑器进行设置,使其在文档中插入空格而不是制表符。
在程序中混合使用制表符和空格可能导致极难解决的问题。 如果你混合使用了制表符和空格,可将文件中所有的制表符转换为空格,大多数编辑器都提供了这样的功能。
2.行长
很多Python程序员都建议每行不超过80字符。最初制定这样的指南时,在大多数计算机中,终端窗口每行只能容纳79字符;现如今的原因是,专业程序员通常会在同一个屏幕上打开多个文件,使用标准行长可以让他们在屏幕上并排打开两三个文件时能同时看到各个文件的完整行。PEP 8还建议注释的行长都不超过72字符,因为有些工具为大型项目自动生成文档时,会在每行注释开头添加格式化字符。
在大多数编辑器中,都可设置一个视觉标志——通常是一条竖线,让你知道不能越过的界线在什么地方。
所以在开始编程前,应该学会如何配置文本编辑器,以使其:
- 在你按制表符键时插入四个空格;
- 显示一条垂直参考线,帮助你遵守行长不能超过79字符的约定。
3.空行
空行不会影响代码的运行,但会影响代码的可读性。Python解释器根据水平缩进情况来解读
代码,但不关心垂直间距。