学习完数据结构之后,我们就能够对之前在第二天中讲过的流程控制工具,添加更多的用法了,这里主要介绍的是for
循环语句和if
与while
条件判断语句。
5.6. 循环的技巧
我们学过的遍历序列for i in range()
、for i in list()
和 for i in tuple()
,都是每次只取出一个元素。技巧性更强的是一次取出两个元素,尤其以字典为例:
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
... print(k, v)
...
gallahad the pure
robin the brave
在字典中循环,用 items()
方法可将关键字和对应的值同时取出。不仅是字典,当在序列(list, tuple, range)中循环时,用 enumerate()
函数可以将索引位置和其对应的值同时取出,用法如下:
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print(i, v)
...
0 tic
1 tac
2 toe
还有更强的用法,用到昨天讲到的zip()
函数。当同时在两个或更多序列中循环时,可以用 zip()
函数将每个序列中的元素按位置逐一进行匹配。如下例就实现了问题和回答的匹配:
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
... print('What is your {0}? It is {1}.'.format(q, a))
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.
接下来是一些针对序列循环的小技巧,如果想逆向循环一个序列时,应该先正向定位序列,然后调用 reversed()
函数:
>>> for i in reversed(range(1, 10, 2)):
... print(i)
...
9
7
5
3
1
如果要按某个指定顺序循环一个序列,可以用 sorted()
函数,即先排序再循环。之所以用sorted()
而不用.sort()
,是因为sorted()
可以在不改动原序列的基础上返回一个新的排好序的序列,而.sort()
会对原序列本身进行排序。如下例就是对集合中的单词按照首字母从小到大的顺序进行循环:
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
... print(f)
...
apple
banana
orange
pear
有时可能会想在循环时修改列表内容,一般来说改为创建一个新列表是比较简单且安全的。如下例就是把列表中的NaN
去掉:
>>> import math
>>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
>>> filtered_data = []
>>> for value in raw_data:
... if not math.isnan(value):
... filtered_data.append(value)
...
>>> filtered_data
[56.2, 51.7, 55.3, 52.5, 47.8]
5.7. 深入条件控制
在while
和 if
条件句中,除了常见的> < >= <= ==
这些比较操作以外,其他任意操作也是允许的,这里主要讲解一些常用的操作和原则:
- 操作符
in
和not in
可以校验一个值是否在(或不在)一个序列里。 - 操作符
is
和is not
比较两个对象是不是同一个对象,这只对像列表这样的可变对象比较重要。注意它们是根据id
进行比较的,不同id
的列表即使内容相同is
也会返回False
;而与之对应的,==
是根据值进行比较,只要内容相同==
就会返回True
。 - 所有的比较操作符都有相同的优先级,且这个优先级比数值运算符低。
- 比较操作可以传递。例如
a < b == c
会校验是否 a 小于 b 并且 b 等于 c。 - 比较操作可以通过布尔运算符
and
和or
来组合,并且比较操作(或其他任何布尔运算)的结果都可以用not
来取反。这些操作符的优先级低于比较操作符;在它们之中,not
优先级最高,or
优先级最低,因此A and not B or C
等价于(A and (not B)) or C
。和之前一样,你也可以在这种式子里使用圆括号。 - 布尔运算符
and
和or
也被称为短路运算符:它们的参数从左至右解析,一旦可以确定结果解析就会停止。例如,如果 A 和 C 为True
而 B 为False
,那么A and B and C
不会解析 C,而直接返回False
。当用作普通值而非布尔值时,短路操作符的返回值通常是最后一个变量,例如:
>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'
string1
空字符串相当于False
,而string2
为True
,故直接短路,表达式返回string2
赋给non_null
。