在上一篇《手把手陪您学Python》22——字典中,我们学习了字典的基本概念,增删改查的方法,以及字典的函数和几个比较重要的方法。在这一篇中,我们会先介绍几个Python中内置的序列函数,之后介绍几个字典的实例,以便大家更好地掌握字典的特性以及在编程中的应用方法。
1、sorted()函数
sorted()函数的作用是将任意序列中的元素进行正序排序,并新建一个已排序的列表进行输出。函数的参数是任意序列,排序时会将其按照可遍历的最小单元进行拆分,之后进行排序。我们之前学习列表时,有一个list.sort()方法,与此类似。
In [1]: sorted("《手把手陪您学Python》") # 字符串排序的输出结果,是由每个字符排序后作为元素的列表
Out[1]: ['P', 'h', 'n', 'o', 't', 'y', '《', '》', '学', '您', '手', '手', '把', '陪']
In [2]: sorted((8, 5, 1))
Out[2]: [1, 5, 8]
In [3]: sorted((8, 5, (1, 2))) # 参数中要排序的元素必须只能是一种数据类型,否则会报错
Out[3]: ---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-d3c8864d6278> in <module>
----> 1 sorted((8, 5, (1, 2))) # 参数中要排序的元素必须只能是一种数据类型,否则会报错
TypeError: '<' not supported between instances of 'tuple' and 'int'
In [4]: sorted(((8, 5), (1, 2))) # 可以都是元组或者列表
Out[4]: [(1, 2), (8, 5)]
In [5]: sorted({3:'A', 2:'B', 1:'C'}) # 字典按照键进行排序,输出时也只输出键排序后的列表
Out[5]: [1, 2, 3]
In [6]: sorted(123) # 数字不能排序,因为数字不能被遍历
Out[6]: ---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-13-2b4e23a052ca> in <module>
----> 1 sorted(123) # 单个数字不能排序,因为数字不能被遍历
TypeError: 'int' object is not iterable
2、reversed()函数
reversed()函数的作用是将序列的元素倒序排列。但不要以为它和sorted()函数的差别只是正序和倒序,其实这里还有比较大的差别。
一是sorted()函数是将序列中的元素按照ASCII的顺序进行正序排序,而reversed()函数不会对序列中的元素进行ASCII的重新排序,而是直接将原序列倒序排列。说起来比较容易误会,通过一个实例看一下就明白了。
In [7]: print(sorted("《手把手陪您学Python》")) # 整体重排序
print(list(reversed("《手把手陪您学Python》"))) # 将原来的顺序倒过来
Out[7]: ['P', 'h', 'n', 'o', 't', 'y', '《', '》', '学', '您', '手', '手', '把', '陪']
['》', 'n', 'o', 'h', 't', 'y', 'P', '学', '您', '陪', '手', '把', '手', '《']
二是sorted()函数可以将序列重新排序后以列表的形式输出,而reversed()函数生成的只是一个迭代器,如果直接输出reversed()的结果会报错(准确来说不是错误,这里这样写会更容易理解),需要使用list()函数将其转化成列表(如上例)。利用reversed()函数的这种特性,可以直接作为for循环的迭代器来使用。
In [8]: reversed("《手把手陪您学Python》") # 直接输出会报错
Out[8]: <reversed at 0x1c6f3f12898>
In [9]: for str in reversed("《手把手陪您学Python》"): # 可以作为for循环的迭代器
print(str, end=' ') # 注意print()函数的参数
Out[9]: 》 n o h t y P 学 您 陪 手 把 手 《
3、enumerate()函数
我们在遍历一个序列的时候,不仅会遍历序列中的每一个元素,有时还需要同时记录每一个元素在序列中的位置。利用我们已学的知识,可以写出这样的代码:
In [10]: lst = ['A', 'B', 'C', 'D', 'E', 'F']
i = 0
for value in lst:
i += 1 # 还记得这个符号吧
print("序列中,第{}个元素是{}".format(i, value))
Out[10]: 序列中,第1个元素是A
序列中,第2个元素是B
序列中,第3个元素是C
序列中,第4个元素是D
序列中,第5个元素是E
序列中,第6个元素是F
由于这种情况很常见,所以Python中内置了一个enumerate()函数,用于直接获取序列的元素及其位置。返回值的结果是一个(i, value)的元组,其中value是元素的值,i是元素的位置索引。请注意,输出结果中,i和value的顺序是不可变的,在给变量命名时要特别注意。
利用enumerate()函数,就可以把上一个实例简写成以下代码了:
In [11]: lst = ['A', 'B', 'C', 'D', 'E', 'F']
for i, value in enumerate(lst): # 变量名即使颠倒,元素的索引也会赋值给前面的变量,元素值也会赋值给后面的变量
print("序列中,第{}个元素是{}".format(i, value))
Out[11]: 序列中,第1个元素是A
序列中,第2个元素是B
序列中,第3个元素是C
序列中,第4个元素是D
序列中,第5个元素是E
序列中,第6个元素是F
看到这里,大家就可以知道了,enumerate()函数的作用其实是输出一个二元的元组,而这种二元元组又正好和字典的键值对非常类似。因此,我们完全可以利用enumerate()函数进行字典的构造,将索引值和元素值映射到字典中。
In [12]: lst = ['A', 'B', 'C', 'D', 'E', 'F'] # 构造序列
dict0 = {} # 定义空字典,必须要定义,否则报错
for i, value in enumerate(lst):
dict0[i] = value
dict0
Out[12]: {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F'}
以上是一个使用序列索引值做字典的键,元素值做字典的值的实例。大家可以试一下,如何能够使用元素值做字典的键,序列索引值做字典的值。
4、zip()函数
zip()函数的作用是将列表、元组或其他序列的元素,按照索引顺序,一一配对,并生成一个由元组构成的列表。配对的序列可以为不同的类型,当序列长度不同时,最终输出的列表长度,由最短的序列决定。
In [13]: seq1 = ['A', 'B', 'C', 'D', 'E'] # 列表元素为字符串
seq2 = (1, 2, 3, 4, 5, 6) # 元组元素为数字,有6个元素,但输出结果以最短的5个元素为准
seq3 = [(1, 2), (1, 2) , (1, 2), (1, 2), (1, 2)] # 列表元素为元组
seq4 = (1, [1, 2], 'W', (1, 2), True) # 元组包括多种元素类型
zipped1 = zip(seq1, seq2, seq3, seq4) # 序列类型和序列内的元素类型都可以不同
list(zipped1) # 转换成列表显示
Out[13]: [('A', 1, (1, 2), 1),
('B', 2, (1, 2), [1, 2]),
('C', 3, (1, 2), 'W'),
('D', 4, (1, 2), (1, 2)),
('E', 5, (1, 2), True)]
In [14]: seq5 = ['A', 'B', 'C', 'D', 'E'] # 列表
seq6 = (1:11, 2:22, 3:33, 4:44, 5:55) # 字典
zipped2 = zip(seq5, seq6) # 字典不能和其它配对,字典间也不能配对
list(zipped2)
Out[14]: File "<ipython-input-25-6db62aa22811>", line 2
seq6 = (1:11, 2:22, 3:33, 4:44, 5:55) # 字典
^
SyntaxError: invalid syntax
zip()函数的一个常用场景是同时遍历多个序列,有时会与enumerate()函数同时使用。
In [15]: for i, (a, b, c, d) in enumerate(zip(seq1, seq2, seq3, seq4)):
print("{0} : {1}, {2}, {3}, {4}".format(i, a, b, c, d)) # 格式化输出的方式,大家还记得吧
Out[15]: 0 : A, 1, (1, 2), 1
1 : B, 2, (1, 2), [1, 2]
2 : C, 3, (1, 2), W
3 : D, 4, (1, 2), (1, 2)
4 : E, 5, (1, 2), True
除了给序列进行“配对”,zip()函数还可以智能地区“拆分”一个类似与“已配对”的序列,而且这个“已配对”的序列,不一定非是列表,还可以是元组等序列。使用的函数还是zip()函数,但是要在参数前加一个*号,变成zip(*)。大家可以理解为zip的逆过程,或者理解为“解压”过程。
In [16]: seq1, seq2, seq3, seq4 = zip(*zip(seq1, seq2, seq3, seq4)) # 利用“解压”过程,可以将配对后的序列再进行还原
print('seq1: ', seq1, '\nseq2: ', seq2,'\nseq3: ', seq3,'\nseq4: ', seq4)
Out[16]: seq1: ('A', 'B', 'C', 'D', 'E')
seq2: (1, 2, 3, 4, 5)
seq3: ((1, 2), (1, 2), (1, 2), (1, 2), (1, 2))
seq4: (1, [1, 2], 'W', (1, 2), True)
In [17]: seq = [(1, 'A'), (2, 'B'), (3, 'C')] # 换个列子能看清楚一些,相当于把行的列表,变成列的列表
a, b = zip(*seq)
print(a, '\n', b)
Out[17]: (1, 2, 3)
('A', 'B', 'C')
通过两个例子,大家是不是已经了解zip(*)的作用了,zip()的作用是将多个序列相同位置的元素合并成元组,再整个合并成列表。zip(*)的作用是将列表中各个元组中相同位置的元素和并成多个元组。(解释起来有点晦涩,大家可以看着实例进行对比)
5、从序列生成字典
如果有两个序列,希望这两个序列能够在字典中按照元素的位置进行配对(一个序列提供键,一个序列提供值),利用zip()函数可以写出这样的代码:
In [18]: key_list = (1, 2, 3)
value_list = ('A', 'B', 'C')
dict1 = {}
for key, value in zip(key_list, value_list):
dict1[key] = value
dict1
Out[18]: {1: 'A', 2: 'B', 3: 'C'}
由于字典本质上是一个2-元组(含有2个元组的元组)的集合,字典可以接受一个2-元组的列表作为参数,因此,可以不使用for循环在zip()后的列表中进行遍历,而直接生成字典:
In [19]: key_list = (1, 2, 3)
value_list = ('A', 'B', 'C')
dict2 = dict(zip(key_list, value_list))
dict2
Out[19]: {1: 'A', 2: 'B', 3: 'C'}
以上就是Python中内置的4中序列函数的介绍,在其中也穿插了一些字典的应用,也给上一篇介绍的字典进行了补充。
在下一篇中,我们继续学习Python的数据结构,将要给大家介绍的是集合,同时也是我们这一阶段学习的最后一种数据结构,敬请关注。
感谢阅读本文!如有任何问题,欢迎留言,一起交流讨论^_^
要阅读《手把手陪您学Python》系列文章的其他篇目,请关注公众号点击菜单选择,或点击下方链接直达。
《手把手陪您学Python》3——PyCharm的安装和配置
《手把手陪您学Python》5——Jupyter Notebook
For Fans:关注“亦说Python”公众号,回复“手23”,即可免费下载本篇文章所用示例语句。