流程控制#
视频
Python 不仅仅需要可以求值的 表达式 与 函数,还需要一些结构用于表达循环和控制等。
Python 语句 就是告诉你的程序应该做什么的句子。
程序由模块构成。
模块包含语句。
语句包含表达式。
表达式建立并处理对象。
真值测试#
所有的对象都有一个固有的布尔值:真或假。
任何非零的数字或非空的对象都是真。
0
、空对象和特殊对象None
被视为假。比较和相等测试是递归地应用于数据结构。
比较和相等测试返回
True
或False
。布尔运算符
and
和or
返回一个真或假的操作对象。一旦知道结果,布尔运算符就会停止评估(“短路”)。
真值判定 |
结果 |
---|---|
|
如果 |
|
如果 |
|
如果 |
比较、相等和真值#
==
操作符测试值的相等性。is
表达式测试对象的一致性。
真值判断:
S1 = 'spam'
S2 = 'spam'
S1 == S2, S1 is S2
(True, True)
比较:
L1 = [1, ('a', 3)]
L2 = [1, ('a', 3)]
L1 == L2, L1 is L2, L1 < L2, L1 > L2
(True, False, False, False)
bool('')
False
短路计算#
or
: 从左到右求算操作对象,然后返回第一个为真的操作对象。and
: 从左到右求算操作对象,然后返回第一个为假的操作对象。
2 or 3, 3 or 2
(2, 3)
[] or 3
3
[] or {}
{}
2 and 3, 3 and 2
(3, 2)
[] and {}
[]
3 and []
[]
断言#
用于测试推断:
num = -1
assert num > 0, 'num 应该为正数!'
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
Cell In[10], line 2
1 num = -1
----> 2 assert num > 0, 'num 应该为正数!'
AssertionError: num 应该为正数!
if
条件#
year = 1990
if year % 4 == 0:
if year % 400 == 0:
print('闰年')
elif year % 100 == 0:
print('平年')
else:
print('闰年')
else:
print('平年')
平年
使用 and
与 or
的短路逻辑简化表达式:
year = 1990
if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
print('闰年')
else:
print('平年')
平年
if
的短路(short-ciecuit)计算:A = Y if X else Z
year = 1990
print('闰年') if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0 else print('平年')
平年
't' if 'spam' else 'f'
't'
for
循环#
遍历序列对象:
for target in object: # 将对象项目分配给目标
statements # 循环体
pass
/...
:空占位语句
for i in range(5):
... # 等价于 pass
list(range(1, 10, 6))
[1, 7]
# 阶乘
x = 1
for i in range(1, 11):
x *= i
print(f'10!={x}')
10!=3628800
Python 的 for
语句迭代列表或字符串等任意序列,元素的迭代顺序与在序列中出现的顺序一致。例如:
# 可以是 Python 的可迭代容器
seq = [1, 2, 3, 4, 5]
for i in seq:
print(i)
1
2
3
4
5
循环的技巧#
在序列中循环时,用 enumerate()
函数可以同时取出位置索引和对应的值:
for i, v in enumerate(['苹果', '相机', '飞机']):
print(i, v)
0 苹果
1 相机
2 飞机
同时循环两个或多个序列时,用 zip()
函数可以将其内的元素一一匹配:
questions = ['名字', '缺点', '最喜爱的颜色']
answers = ['Judy', '比较懒', '天空蓝']
for q, a in zip(questions, answers):
print(f'你的 {q} 是什么? 答案是 {a}。')
你的 名字 是什么? 答案是 Judy。
你的 缺点 是什么? 答案是 比较懒。
你的 最喜爱的颜色 是什么? 答案是 天空蓝。
逆向循环序列时,先正向定位序列,然后调用 reversed()
函数:
for i in reversed(range(1, 10, 2)):
print(i)
9
7
5
3
1
按指定顺序循环序列,可以用 sorted()
函数,在不改动原序列的基础上,重新返回一个序列:
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for i in sorted(basket, key=len):
print(i)
pear
apple
apple
orange
orange
banana
使用 set()
去除序列中的重复元素。使用 sorted()
加 set()
则按排序后的顺序,循环遍历序列中的唯一元素:
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print(f)
apple
banana
orange
pear
序列和其他类型的比较#
序列对象可以与相同序列类型的其他对象比较。这种比较使用 字典式 顺序:
首先,比较首个元素,如果不相等,则可确定比较结果;如果相等,则比较之后的元素,以此类推,直到其中一个序列结束。
如果要比较的两个元素本身是相同类型的序列,则递归地执行字典式顺序比较。
如果两个序列中所有的对应元素都相等,则两个序列相等。
如果一个序列是另一个的初始子序列,则较短的序列可被视为较小(较少)的序列。
对于字符串来说,字典式顺序使用 Unicode 码位序号排序单个字符。
下面列出了一些比较相同类型序列的例子:
(1, 2, 3) < (1, 2, 4)
True
[1, 2, 3] < [1, 2, 4]
True
'ABC' < 'C' < 'Pascal' < 'Python' # 支持链式比较
True
(1, 2, 3, 4) < (1, 2, 4)
True
(1, 2) < (1, 2, -1)
True
(1, 2, 3) == (1.0, 2.0, 3.0)
True
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)
True
while
循环#
while
循环结构:
初值条件
while test: # 循环测试
statements # 循环体
x = 'spam'
while x: # 直至耗尽 x
print(x, end=' ')
x = x[1:]
spam pam am m
x = 1 # 初值条件
while x <= 100: # 终止条件
print(x)
x += 27
1
28
55
82
Callataz 猜想#
备注
任意取一个正整数 \(n\),如果 \(n\) 是一个偶数,则除以 \(2\) 得到 \(n/2\); 如果 \(n\) 是一个奇数,则乘以 \(3\) 加 \(1\) 得到 \(3n+1\),重复以上操作,我们将得到一串数字。
Collatz 猜想:任何正整数 \(n\) 参照以上规则,都将回归 \(1\)。
def collatz_guess(num):
assert num > 0, 'num 必须为正数'
while num != 1:
if num % 2 == 0:
# 保证 num 在接下来的运算为整数
num //= 2
else:
num *= 3
num += 1
return num
collatz_guess(75)
1
斐波那契数列#
备注
斐波那契数列:
def fib(n): # 写出斐波那契数列,直到n
"""打印直到 n 的斐波那契数列"""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
备注
第一行中的 多重赋值:变量
a
和b
同时获得新值0
和1
。最后一行又用了一次多重赋值,这体现在右表达式在赋值前就已经求值了。右表达式求值顺序为从左到右。
continue
#
continue
:跳到最近所在循环的开头处(来到循环的首行)
x = 10
while x:
x -= 1
if x % 2 != 0:
continue # 跳过打印
print(x, end=' ')
8 6 4 2 0
for num in range(2, 8):
if num % 2 == 0:
print(f"{num} 是偶数")
continue
print(f"{num} 是奇数")
2 是偶数
3 是奇数
4 是偶数
5 是奇数
6 是偶数
7 是奇数
else
子句#
break
:跳出所在的最内层循环(跳过整个循环语句)else
:只有当循环正常离开时才会执行(也就是没有碰到break
语句)
和循环 else
子句结合,break
语句通常可以忽略所需要的搜索状态标志位。
def fator(y):
'''仅仅打印 y 的首个因子'''
x = y // 2
while x > 1:
if y % x == 0:
print(y, '有因子', x)
break
x -= 1
else: # 没有碰到 break 才会执行
print(y, '是质数!')
fator(7), fator(88), fator(45);
7 是质数!
88 有因子 44
45 有因子 15
看一个更复杂的例子:
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print(n, '=', x, 'x', n//x)
break
else:
# 循环失败,没有找到一个因子
print(n, '是质数!')
2 是质数!
3 是质数!
4 = 2 x 2
5 是质数!
6 = 2 x 3
7 是质数!
8 = 2 x 4
9 = 3 x 3