作者:Yong Cui, Ph.D.
翻译:老齐
与本文相关的图书推荐:《Python大学实用教程》
概要
在Python中,for循环经常被用于获得序列或者容器类的元素,比较让人熟知的就是针对可迭代对象的循环。for循环的基本语法如下:
for item in iterable:
# do something here
通常,可迭代对象包括序列(如:列表、元组和range对象)和容器类对象(如字典、集合),下面看一些示例:
>>> # 循环列表
>>> for item in [1, 2, 3]:
... pass
...
>>> # 循环元组
>>> for item in (1, 2, 3):
... pass
...
>>> # 循环range
>>> for item in range(3):
... pass
...
>>> # 循环字典
>>> for item in {0: 'a', 1: 'b', 2: 'c'}:
... pass
...
>>> # 循环集合
>>> for item in set([1, 2, 3]):
... pass
...
上面那些示例中的循环对象,都是基本的可迭代对象,此外,我们还可以用用内置函数,让for循环中的操作更优化,它们是:enumerate(), reversed(), sorted(), 和 zip()
,在本文中,我将向您说明这些函数的用法。
enumerate()
函数
第一个要介绍的内置函数是enumerate(iterable, start=0)
,它的参数是一个可迭代对象,返回枚举对象。参数start
的默认值是0,也可以随意设置,它表示迭代开始编号。
例如,有一个列表,里面是公司员工的姓名,我们想给每个员工确定一个员工ID,可以使用enumerate()
函数这样实现:
>>> employees = ['John', 'Danny', 'Jennifer']
>>>
>>> for id_number, name in enumerate(employees, start=30001):
... print(f"{name}'s employee ID #: {id_number}")
...
John's employee ID #: 30001
Danny's employee ID #: 30002
Jennifer's employee ID #: 30003
如上所示,我们创建了一个包含员工姓名的列表,它作为可迭代对象传给函数enumerate()
,并且,start
参数设置为30001
,表示员工ID开始的编号。如你所见,每次循环,我们就得到了编号和列表中相应的元素。最后,根据我们的要求将结果打印出来。
reversed()
函数
第二个内置函数reversed(seq)
,它以序列对象为参数(例如:元组和列表),返回一个反序的迭代器对象,本质上,这个函数的作用是将传入的序列对象中元素的排列顺序反序。
假设你的午餐如下面的列表所示,因为新冠病毒,就不要下馆子了。在接下来的一周内,你也不知道怎么变换吃的花样,于是,就干脆将列表中的食物反序吧。为此,我们可以使用reversed()
函数。
>>> meals = ['pizza', 'hamberger', 'pasta', 'ramen', 'salad']
>>>
>>> for meal in reversed(meals):
... print(meal)
...
salad
ramen
pasta
hamberger
pizza
由上面代码可知,利用函数reversed()
,得到了按变量meals
中元素的相反顺序排列的食物。注意,对于list
对象而言,也有一个reverse()
方法,它能够原地将列表反序,即不会返回新的对象,或者说,只返回了None
,这个操作不能用于for循环中,比如:
>>> for meal in meals.reverse():
... print(meal)
...
Traceback (most recent call last):
File "", line 1, in
TypeError: 'NoneType' object is not iterable
>>> meals.reverse() is None
True
sorted()
第三个内置函数式sorted(iterable, *, key=None, reverse=False)
,其参数是可迭代对象,返回一个新的排序了的列表。需要注意两个关键词参数的使用,key
,通过它可以指定一个含有一个参数的函数,用这个函数比较可迭代对象中的每个元素;reverse
用于指定排序方式,如果为True
表示反序。
假设一个员工列表,其中每个元素表示一个员工对象,每个员工对象包含名字和上一季度的绩效考核分数。我们需要根据绩效考核的分数对员工进行排序。下面的代码演示了实现方法:
>>> class Employee:
... def __init__(self, name, score):
... self.name = name
... self.score = score
...
>>> employee0 = Employee('John Smith', 95)
>>> employee1 = Employee('Mike Brown', 99)
>>> employee2 = Employee('Jennifer Thompson', 97)
>>> employees = [employee0, employee1, employee2]
>>>
>>> for employee in sorted(employees, key=lambda x: x.score, reverse=True):
... print(f'{employee.name} Score: {employee.score}')
...
Mike Brown Score: 99
Jennifer Thompson Score: 97
John Smith Score: 95
在上面的代码中,我们自定义了一个类Employee
,用它来创建员工实例,并存储姓名和分数。然后创建3个员工实例,并将这三个员工实例存入一个列表中,这个列表将作为可迭代对象传给sorted()
函数。**注意:**参数key
的值,我们编写了一个lambda函数,它会对列表中每个员工实例的score
属性进行比较。reverse
参数的值设置为True
,在输出结果中,会按照分数从大到小排序。
与reversed()
类似,列表对象有一个sort()
方法,它能够对列表进行原地排序,所以,我们不能直接在for循环中用list.sort()
方法。另外一个重要区别是,sorted()
函数可以用任何可迭代对象为参数(比如:元组、字典),这使它在排序上的能力比sort()
方法强悍,后者只能作为列表对象的方法。
zip()
函数
第四个内置函数是zip(*iterables)
,可以用一个或多个可迭代对象作为参数,会返回一个迭代器对象,并且将参数中的可迭代对象的元素对应合并,合并后的元素以元组形式组合,如合并后的第1个元组中包含作为参数的每个可迭代对象中的第1个元素。
假设有两个整数作为元素的列表,我们需要相对应整数的乘积,就可以使用zip()
函数来实现这个操作:
>>> numbers0 = [4, 5, 6]
>>> numbers1 = [11, 12, 13]
>>>
>>> for j, k in zip(numbers0, numbers1):
... print(f'{j} * {k} = {j*k}')
...
4 * 11 = 44
5 * 12 = 60
6 * 13 = 78
在上面的代码中,首先创建了两个列表numbers0
和numbers1
,将它们传给zip()
函数,返回的元组中包含了对应的数字。
一个需要注意的是,zip()
函数返回的迭代器对象的长度,是以参数中最短的可迭代对象为准。例如下面的示例,两个字符串的长度不同,最后得到的迭代器对象只有3个元组,并且,必须用list()
函数对迭代器对象进行转换,才能显示其具体内容。
>>> letters0 = 'abcde'
>>> letters1 = 'xyz'
>>> list(zip(letters0, letters1))
[('a', 'x'), ('b', 'y'), ('c', 'z')]
要点总结
本文主要探讨了for循环中使用的4个内置函数。这些函数的特点如下:
enumerate()
函数允许创建循环的计数起点。reversed()
函数的作用主要是对序列进行反序。sorted()
函数能够对任何可迭代对象进行排序,并且可以灵活地指定任何排序关键词。zip()
函数主要用于组合可迭代对象中对应的元素,并返回一个迭代器对象。
原文链接:https://medium.com/swlh/level-up-for-loops-in-python-with-4-simple-functions-da01173a834c
专注于软件和AI的公众号
老齐教室
觉得好看,就点这里???