04.循环结构.md 6.6 KB
Newer Older
J
jackfrued 已提交
1
## 循环结构
2

3
### 应用场景
4

5
我们在写程序的时候,一定会遇到需要重复执行某条或某些指令的场景。例如用程序控制机器人踢足球,如果机器人持球而且还没有进入射门范围,那么我们就要一直发出让机器人向球门方向移动的指令。在这个场景中,让机器人向球门方向移动就是一个需要重复的动作,当然这里还会用到上一课讲的分支结构来判断机器人是否持球以及是否进入射门范围。再举一个简单的例子,如果要实现每隔1秒中在屏幕上打印一次“hello, world”并持续打印一个小时,我们肯定不能够直接把`print('hello, world')`这句代码写3600遍,这里同样需要循环结构。
6

7
循环结构就是程序中控制某条或某些指令重复执行的结构。在Python中构造循环结构有两种做法,一种是`for-in`循环,一种是`while`循环。
8 9 10

### for-in循环

11
如果明确的知道循环执行的次数或者要对一个容器进行迭代(后面会讲到),那么我们推荐使用`for-in`循环,例如下面代码中计算1~100求和的结果($\displaystyle \sum \limits_{n=1}^{100}n$)。 
12 13 14 15 16 17 18 19 20 21 22

```Python
"""
用for循环实现1~100求和

Version: 0.1
Author: 骆昊
"""

sum = 0
for x in range(101):
J
jackfrued 已提交
23
    sum += x
24 25 26
print(sum)
```

27
需要说明的是上面代码中的`range(1, 101)`可以用来构造一个从1到100的范围,当我们把这样一个范围放到`for-in`循环中,就可以通过前面的循环变量`x`依次取出从1到100的整数。当然,`range`的用法非常灵活,下面给出了一个例子:
28

29 30 31 32
- `range(101)`:可以用来产生0到100范围的整数,需要注意的是取不到101。
- `range(1, 101)`:可以用来产生1到100范围的整数,相当于前面是闭区间后面是开区间。
- `range(1, 101, 2)`:可以用来产生1到100的奇数,其中2是步长,即每次数值递增的值。
- `range(100, 0, -2)`:可以用来产生100到1的偶数,其中-2是步长,即每次数字递减的值。
33 34 35 36 37 38 39 40 41 42 43 44 45

知道了这一点,我们可以用下面的代码来实现1~100之间的偶数求和。

```Python
"""
用for循环实现1~100之间的偶数求和

Version: 0.1
Author: 骆昊
"""

sum = 0
for x in range(2, 101, 2):
J
jackfrued 已提交
46
    sum += x
47 48 49
print(sum)
```

50
当然,也可以通过在循环中使用分支结构的方式来实现相同的功能,代码如下所示。
51 52 53 54 55 56 57 58 59 60 61

```Python
"""
用for循环实现1~100之间的偶数求和

Version: 0.1
Author: 骆昊
"""

sum = 0
for x in range(1, 101):
J
jackfrued 已提交
62 63
    if x % 2 == 0:
        sum += x
64 65 66
print(sum)
```

67 68
> **说明**:相较于上面直接跳过奇数的做法,下面这种做法很明显并不是很好的选择。

69 70
### while循环

71 72 73
如果要构造不知道具体循环次数的循环结构,我们推荐使用`while`循环。`while`循环通过一个能够产生或转换出`bool`值的表达式来控制循环,表达式的值为`True`则继续循环;表达式的值为`False`则结束循环。

下面我们通过一个“猜数字”的小游戏来看看如何使用`while`循环。猜数字游戏的规则是:计算机出一个1到100之间的随机数,玩家输入自己猜的数字,计算机给出对应的提示信息(大一点、小一点或猜对了),如果玩家猜中了数字,计算机提示用户一共猜了多少次,游戏结束,否则游戏继续。
74 75 76 77 78 79 80 81 82 83 84 85 86

```Python
"""
猜数字游戏

Version: 0.1
Author: 骆昊
"""
import random

answer = random.randint(1, 100)
counter = 0
while True:
J
jackfrued 已提交
87 88 89 90 91 92 93 94 95
    counter += 1
    number = int(input('请输入: '))
    if number < answer:
        print('大一点')
    elif number > answer:
        print('小一点')
    else:
        print('恭喜你猜对了!')
        break
96 97
print('你总共猜了%d次' % counter)
if counter > 7:
J
jackfrued 已提交
98
    print('你的智商余额明显不足')
99 100
```

J
jackfrued 已提交
101
上面的代码中使用了`break`关键字来提前终止循环,需要注意的是`break`只能终止它所在的那个循环,这一点在使用嵌套的循环结构(下面会讲到)需要引起注意。除了`break`之外,还有另一个关键字是`continue`,它可以用来放弃本次循环后续的代码直接让循环进入下一轮。
102 103 104 105 106 107 108 109 110 111 112 113

和分支结构一样,循环结构也是可以嵌套的,也就是说在循环中还可以构造循环结构。下面的例子演示了如何通过嵌套的循环来输出一个九九乘法表。

```Python
"""
输出乘法口诀表(九九表)

Version: 0.1
Author: 骆昊
"""

for i in range(1, 10):
J
jackfrued 已提交
114 115 116
    for j in range(1, i + 1):
        print('%d*%d=%d' % (i, j, i * j), end='\t')
    print()
117 118 119 120
```

### 练习

J
jackfrued 已提交
121 122 123 124 125
#### 练习1:输入一个正整数判断是不是素数。

> **提示**:素数指的是只能被1和自身整除的大于1的整数。

参考答案:
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140

```Python
"""
输入一个正整数判断它是不是素数

Version: 0.1
Author: 骆昊
Date: 2018-03-01
"""
from math import sqrt

num = int(input('请输入一个正整数: '))
end = int(sqrt(num))
is_prime = True
for x in range(2, end + 1):
J
jackfrued 已提交
141 142 143
    if num % x == 0:
        is_prime = False
        break
144
if is_prime and num != 1:
J
jackfrued 已提交
145
    print('%d是素数' % num)
146
else:
J
jackfrued 已提交
147
    print('%d不是素数' % num)
148 149
```

J
jackfrued 已提交
150 151
#### 练习2:输入两个正整数,计算它们的最大公约数和最小公倍数。

152 153
> **提示**:两个数的最大公约数是两个数的公共因子中最大的那个数;两个数的最小公倍数则是能够同时被两个数整除的最小的那个数。

J
jackfrued 已提交
154
参考答案:
155 156 157

```Python
"""
J
jackfrued 已提交
158
输入两个正整数计算它们的最大公约数和最小公倍数
159 160 161 162 163 164 165 166

Version: 0.1
Author: 骆昊
Date: 2018-03-01
"""

x = int(input('x = '))
y = int(input('y = '))
J
jackfrued 已提交
167
# 如果x大于y就交换x和y的值
168
if x > y:
J
jackfrued 已提交
169
    # 通过下面的操作将y的值赋给x, 将x的值赋给y
J
jackfrued 已提交
170
    x, y = y, x
171
# 从两个数中较小的数开始做递减的循环
172
for factor in range(x, 0, -1):
J
jackfrued 已提交
173 174 175 176
    if x % factor == 0 and y % factor == 0:
        print('%d和%d的最大公约数是%d' % (x, y, factor))
        print('%d和%d的最小公倍数是%d' % (x, y, x * y // factor))
        break
177 178
```

J
jackfrued 已提交
179
#### 练习3:打印如下所示的三角形图案。
180

J
jackfrued 已提交
181
```
182 183 184 185 186
*
**
***
****
*****
J
jackfrued 已提交
187
```
188

J
jackfrued 已提交
189
```
190 191 192 193 194
    *
   **
  ***
 ****
*****
J
jackfrued 已提交
195
```
196

J
jackfrued 已提交
197
```
198 199 200 201 202
    *
   ***
  *****
 *******
*********
J
jackfrued 已提交
203 204 205 206 207 208 209
```

参考答案:

```Python
"""
打印三角形图案
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236

Version: 0.1
Author: 骆昊
"""

row = int(input('请输入行数: '))
for i in range(row):
    for _ in range(i + 1):
        print('*', end='')
    print()


for i in range(row):
    for j in range(row):
        if j < row - i - 1:
            print(' ', end='')
        else:
            print('*', end='')
    print()

for i in range(row):
    for _ in range(row - i - 1):
        print(' ', end='')
    for _ in range(2 * i + 1):
        print('*', end='')
    print()
```