-
Notifications
You must be signed in to change notification settings - Fork 0
/
2.control-flow.md
558 lines (420 loc) · 21.2 KB
/
2.control-flow.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
Python 中的控制流
---
### 概述
- 条件语句
- 布尔表达式
- For 和 While 循环
- Break 和 Continue
- Zip 和 Enumerate
- 列表推导式
---
### 条件语句
- If 语句:是一种条件语句,根据条件为 true 还是 false 运行或执行相关代码
```python
if phone_balance < 5:
phone_balance += 10
bank_balance -= 10
```
- If、Elif、Else:
```python
if season == 'spring':
print('plant the garden!')
elif season == 'summer':
print('water the garden!')
elif season == 'fall':
print('harvest the garden!')
elif season == 'winter':
print('stay indoors!')
else:
print('unrecognized season')
```
说明:
* `if`:if 语句必须始终以 if 条件开始,其中包含第一个要检查的条件。如果该条件为 True,Python 将运行这个 if 块中的缩进代码,然后跳到 if 语句之后的剩余代码。
* `elif`:elif 条件用来检查其他条件(前提是 if 语句中之前的条件结果为 False)。可以从示例中看出,可以使用多个 elif 块处理不同的情形。
* `else`:最后是 else 条件,它必须位于 if 语句的末尾。该条件语句不需要条件。如果 if 语句中所有前面的语句结果都为 False 时,将运行 else 块中的代码。
- 缩进:在 Python 中,我们使用缩进来封装代码块,缩进通常是四个空格一组。请严格遵守该惯例,因为更改缩进会完全更改代码的含义。
### 条件语句[相关练习]
- 请编写一个 if 语句,使竞争者能够根据自己的得分知道获得了哪个奖品,得分存储在整型变量 points 中。
| 得分 | 奖励 | Prize in English
|---|----|-----
| 1 - 50 | 木质兔子玩偶 | wooden rabbit
| 51 - 150 | 没有奖品 | no prize
| 151 - 180 | 极薄薄荷 | wafer-thin mint
| 181 - 200 | 企鹅 | penguin
所有的上下限都包含在内,points 只能是正整数,最大值为 200。
在你的 if 语句中,将 result 变量赋给一个根据 points 的值存储相应消息的字符串。如果赢得了奖品,消息内容应该是 "Congratulations! You won a [prize name]!”,“prize name”应替换成相应的奖品。如果没有赢得奖品,消息内容应该是 "Oh dear, no prize this time."
```python
points = 174 # use this input to make your submission
# write your if statement here
if points >= 1 and points <= 50:
result = "Congratulations! You won a wooden rabbit!"
elif points >= 51 and points <= 150:
result = "Oh dear, no prize this time."
elif points >= 151 and points <= 180:
result = "Congratulations! You won a wafer-thin mint!"
elif points >= 181 and points <= 200:
result = "Congratulations! You won a penguin!"
print(result)
```
### 复杂的布尔表达式
- If 语句有时候会使用更加复杂的条件布尔表达式。可能包括多个比较运算符、逻辑运算符,甚至包括算式。
```python
if 18.5 <= weight / height**2 < 25:
print("BMI is considered 'normal'")
if is_raining and is_sunny:
print("Is there a rainbow?")
if (not unsubscribed) and (location == "USA" or location == "CAN"):
print("send email")
```
注意:对于非常复杂的条件,你可能需要结合使用 and、or 和 not。使用括号可以使运算符组合更清晰。无论是简单还是复杂的条件,if 语句中的条件都必须是结果为 True 或 False 的布尔表达式,该值决定了 if 语句中的缩进代码块是否执行。
### 正反面示例
- 请勿使用 `True` 或 `False` 作为条件
```python
# Bad example
if True:
print("This indented code will always get run.")
```
注意:虽然 `True` 是一个有效的布尔表达式,但不是有用的条件,因为它始终为 `True`,因此缩进代码将始终运行。同样,`if False` 也不应使用,该 `if` 语句之后的语句将从不运行。
```python
# Another bad example
if is_cold or not is_cold:
print("This indented code will always get run.")
```
同样,使用你知道将始终结果为 `True` 的条件(例如上述示例)也是毫无用途的。布尔表达式只能为 `True` 或 `False`,因此 is_cold 或 not is_cold 将始终为 `True`,缩进代码将始终运行。
- 在使用逻辑运算符编写表达式时,要谨慎: 逻辑运算符 `and`、`or` 和 `not` 具有特定的含义,与字面英文意思不太一样。确保布尔表达式的结果和你预期的一样。
```python
# Bad example
if weather == "snow" or "rain":
print("Wear boots!")
```
这段代码在 Python 中是有效的,但不是布尔表达式,虽然读起来像。原因是 or 运算符右侧的表达式 "rain" 不是布尔表达式,它是一个字符串。
- 请勿使用 `== True` 或 `== False` 比较布尔变量: 这种比较没必要,因为布尔变量本身是布尔表达式。
```python
# Bad example
if is_cold == True:
print("The weather is cold!")
```
这是一个有效的条件,但是我们可以使用变量本身作为条件,使代码更容易读懂:
```python
# Good example
if is_cold:
print("The weather is cold!")
```
备注:如果你想检查布尔表达式是否为 `False`,可以使用 `not` 运算符。
- 在 python 中被视为 `False` 的大多数内置对象
* 定义为 false 的常量:`None` 和 `False
* 任何数字类型的零:`0`、`0.0`、`0j`、`Decimal(0)`、`Fraction(0, 1)`
* 空序列和空集合:`""`、`()`、`[]`、`{}`、`set()`、`range(0)`
* 示例代码如下:
```python
errors = 3
if errors:
print("You have {} errors to fix!".format(errors))
else:
print("No errors to fix!")
```
在上述代码中,errors 的真假值为 `True`,因为它是非零数字,因此输出了错误消息。
### Python 中的For循环
> Python 有两种类型的循环:for 循环和 while 循环。for 循环用来遍历可迭代对象。
- 可迭代对象是每次可以返回其中一个元素的对象
* 包括字符串、列表和元组等序列类型,以及字典和文件等非序列类型。还可以使用迭代器和生成器定义可迭代对象
- For 循环示例:
```python
# iterable of cities
cities = ['new york city', 'mountain view', 'chicago', 'los angeles']
# for loop that iterates over the cities list
for city in cities:
print(city.title())
```
- For 循环的组成部分:
* 循环的第一行以关键字 `for` 开始,表示这是一个 `for` 循环
* 然后是 `iteration_variable in iterable`,表示正在被遍历的是可迭代的对象,并且用迭代变量表示当前正在被处理的可迭代对象的元素。在此示例中,迭代变量 `city` 在第一次迭代时将是 "new york city",在第二次迭代时将是 mountain view。
* `for` 循环头部始终以英文冒号 `:` 结束。
* `for` 循环头部之后的是在此 `for` 循环的每次迭代时运行的缩进代码块。在此块中,我们可以使用迭代变量访问当前正在被处理的元素的值。
* 你可以随意命名迭代变量。常见模式是为迭代变量和可迭代对象指定相同的名称,但是分别使用单复数形式(例如 'city' 和 'cities')
- For 循环创建和修改列表:
```python
# Creating a new list
cities = ['new york city', 'mountain view', 'chicago', 'los angeles']
capitalized_cities = []
for city in cities:
capitalized_cities.append(city.title())
```
- 修改列表稍微复杂些,需要使用新的函数:`range()`:
- `range()` 是一个内置函数,用于创建不可变的数字序列。它有三个参数,必须都为整数。`range(start=0, stop, step=1)`
* `start`是该序列的第一个数字,`stop`比该序列的最后一个数字大 1,`step`是该序列中每个数字之间的差。如果未指定的话,`start`默认为 0,`step` 默认为 1(即上述 =0 和 =1)。
* 如果你在 `range()` 的括号里指定一个参数,它将用作 `stop` 的值,另外两个参数使用默认值。
E.g. `list(range(4))` 返回 `[0, 1, 2, 3]`
* 如果你在 `range()` 的括号里指定两个参数,它们将用作 `start` 和 `stop` 的值,`step` 将使用默认值。 E.g. `list(range(2, 6))` 返回 `[2, 3, 4, 5]`
* 注意,在这些示例中,我们将 range 封装在列表中。因为 range 本身的输出是一个 range 对象。我们可以通过将其转换为列表或在 for 循环中遍历它,查看 range 对象中的值集合。
- 我们可以使用 range 函数为 cities 列表中的每个值生成索引。这样我们便可以使用 cities[index] 访问列表中的元素,以便直接修改 cities 列表中的值。
```python
cities = ['new york city', 'mountain view', 'chicago', 'los angeles']
for index in range(len(cities)):
cities[index] = cities[index].title()
```
- 虽然修改列表是 `range` 函数的一个用途,但是并非只有这一个用途。你将经常使用 `range` 和 `for` 循环重复某个操作一定的次数。
```python
for i in range(3)
print("Hi!")
```
### For 循环[相关练习]
- 写一个遍历 names 列表以创建 usernames 列表的 for 循环。要为每个姓名创建用户名,使姓名全小写并用下划线代替空格。对以下列表运行 for 循环:<br>
`names = ["Joey Tribbiani", "Monica Geller", "Chandler Bing", "Phoebe Buffay"]`
应该会创建列表:<br>
`usernames = ["joey_tribbiani", "monica_geller", "chandler_bing", "phoebe_buffay"]`<br>
解决方案如下:<br>
```python
names = ["Joey Tribbiani", "Monica Geller", "Chandler Bing", "Phoebe Buffay"]
usernames = []
# write your for loop here
for name in names:
usernames.append(name.lower().replace(" ", "_"))
print(usernames)
```
- 假设我们不想创建新的列表,而是修改 names 列表本身,并编写以下代码。下面的代码有什么作用?
```python
names = ["Joey Tribbiani", "Monica Geller", "Chandler Bing", "Phoebe Buffay"]
for name in names:
name = name.lower().replace(" ", "_")
print(names)
```
分析: `这段代码没有效果。` 在每次迭代时,`name` 变量设为从该列表中获取的一个字符串。然后赋值语句创建一个新的字符串 `(name.lower().replace(" ", "_"))` 并将 `name` 变量更改为该字符串。要修改该列表,你必须使用 `range` 对该列表本身操作。
- 写一个使用 `range()` 遍历 `usernames` 中的职位以修改该列表的 `for` 循环。和上一道练习一样,将每个姓名改成全小写形式并用下划线代替空格。运行 `for` 循环后,以下列表:<br>
`usernames = ["Joey Tribbiani", "Monica Geller", "Chandler Bing", "Phoebe Buffay"]`<br>
应该更改为:<br>
`usernames = ["joey_tribbiani", "monica_geller", "chandler_bing", "phoebe_buffay"]`
解决方案如下:
```python
usernames = ["Joey Tribbiani", "Monica Geller", "Chandler Bing", "Phoebe Buffay"]
# escreva seu loop for aqui
for index in range(len(usernames)):
usernames[index] = usernames[index].lower().replace(" ", "_")
print(usernames)
```
- 标记计数器: 写一个 `for` 循环,用于遍历字符串列表 `tokens` 并数一下有多少个 XML 标记。
解决方案如下:
```python
tokens = ['<greeting>', 'Hello World!', '</greeting>']
count = 0
# write your for loop here
for t in tokens:
if t[0] == '<' and t[-1] == '>':
count += 1
print(count)
```
- 创建 HTML 列表: 写一个 `for` 循环,用于遍历字符串列表并创建单个字符串 `html_str`,它是一个 `HTML` 列表。例如,如果列表是 `items = ['first string', 'second string]`,输出 `html_str` 应该会输出:
```python
<ul>
<li>first string</li>
<li>second string</li>
</ul>
```
解决方案如下:
```python
items = ['first string', 'second string']
html_str = "<ul>\n"
for item in items:
html_str += "<li>" + item + "</li>\n"
html_str += "</ul>"
print(html_str)
```
### Python 中的While循环
- For 循环是一种“有限迭代”,意味着循环主体将运行预定义的次数。这与“无限迭代”循环不同,无限迭代循环是指循环重复未知次数,并在满足某个条件时结束,while 循环正是这种情况。下面是一个 while 循环的示例:
```python
card_deck = [4, 11, 8, 5, 13, 2, 8, 10]
hand = []
# adds the last element of the card_deck list to the hand list
# until the values in hand add up to 17 or more
while sum(hand) <= 17:
hand.append(card_deck.pop())
```
这个示例包含两个函数。`sum` 返回列表中的元素之和,`pop` 是一个列表方法,它会从列表中删除最后一个元素并返回该元素。
- While 循环的组成部分:
* 第一行以关键字 `while` 开始,表示这是一个 `while` 循环。
* 然后是要检查的条件。在此示例中是 `sum(hand) <= 17`。
* `while` 循环头部始终以冒号 `:` 结束。
* 该头部之后的缩进部分是 `while` 循环的主体。如果 `while` 循环的条件为 `true`,该循环的主体将被执行。每次运行循环主体时,条件将被重新评估。这个检查条件然后运行循环的流程将重复,直到该表达式变成 `False`。
* 注意: 循环的缩进主体应该至少修改测试表达式中的一个变量。如果测试表达式的值始终不变,就会变成无限循环!
### Python 中的While循环[相关练习]
- 写一个 while 循环,用于计算比整数 limit 小的最大平方数,并将其存储在变量 nearest_square 中。平方数是整数乘以自己后的积,例如 36 是一个平方数,因为它等于 6*6。例如,如果 limit 是 40,你的代码应该将 nearest_square 设为 36。<br>
解决方案:<br>
```python
limit = 40
num = 0
# write your while loop here
while (num+1)**2 < limit:
num += 1
nearest_square = num**2
print(nearest_square)
```
### Python 中的Break 和 Continue
- break:控制何时循环应该结束
- continue 跳过循环的一次迭代
- 示例练习:用 `break` 语句写一个循环,用于创建刚好长 140 个字符的字符串 `news_ticker`。你应该通过添加 `headlines` 列表中的新闻标题创建新闻提醒,在每个新闻标题之间插入空格。如果有必要的话,从中间截断最后一个新闻标题,使 `news_ticker` 刚好长 140 个字符:<br>
解决方案如下:
```python
headlines = ["Local Bear Eaten by Man",
"Legislature Announces New Laws",
"Peasant Discovers Violence Inherent in System",
"Cat Rescues Fireman Stuck in Tree",
"Brave Knight Runs Away",
"Papperbok Review: Totally Triffic"]
news_ticker = ""
for item in headlines:
news_ticker += item + " "
if len(news_ticker) >= 140:
news_ticker = news_ticker[:140]
break
print(news_ticker) # Local Bear Eaten by Man Legislature Announces New Laws Peasant Discovers Violence Inherent in System Cat Rescues Fireman Stuck in Tree Brave
print(len(news_ticker)) # 140
```
### Python 中的 Zip
- zip的作用:可以在处理循环时用到,返回一个将多个可迭代对象组合成一个元组序列的迭代器。每个元组都包含所有可迭代对象中该位置的元素。
```python
my_zip = list(zip(['a', 'b', 'c'], [1, 2, 3]))
print(my_zip) # [('a', 1), ('b', 2), ('c', 3)]
```
- 正如 `range()` 一样,我们需要将其转换为列表或使用循环进行遍历以查看其中的元素。
```python
letters = ['a', 'b', 'c']
nums = [1, 2, 3]
for letter, num in zip(letters, nums):
print("{}: {}".format(letter, num))
```
输出如下:<br>
```log
a: 1
b: 2
c: 3
```
- 除了可以将两个列表组合到一起之外,还可以使用星号拆封列表,返回的是单个元组
```python
some_list = [('a', 1), ('b', 2), ('c', 3)]
letters, nums = zip(*some_list)
print(letters) # ('a', 'b', 'c')
print(nums) # (1, 2, 3)
```
### Python 中的 Enumerate
- `enumerate` 是一个会返回元组迭代器的内置函数,这些元组包含列表的索引和值。当你需要在循环中获取可迭代对象的每个元素及其索引时,将经常用到该函数。
- 示例代码:
```python
letters = ['a', 'b', 'c', 'd', 'e']
for i, letter in enumerate(letters):
print(i, letter)
```
输出如下:<br>
```log
0 a
1 b
2 c
3 d
4 e
```
### Python 中的 Zip 和 Enumerate[相关练习]
- 使用 `zip` 写一个 `for` 循环,该循环会创建一个字符串,指定每个点的标签和坐标,并将其附加到列表 points。每个字符串的格式应该为 `label: x, y, z`。例如,第一个坐标的字符串应该为 `F: 23, 677, 4`。
解决方案:
```python
x_coord = [23, 53, 2, -12, 95, 103, 14, -5]
y_coord = [677, 233, 405, 433, 905, 376, 432, 445]
z_coord = [4, 16, -6, -42, 3, -6, 23, -1]
labels = ["F", "J", "A", "Q", "Y", "B", "W", "X"]
points = []
# write your for loop here
for label, x, y, z in zip(labels, x_coord, y_coord, z_coord):
points.append(label+": " + str(x) + ', ' + str(y) + ', ' + str(z))
for point in points:
print(point)
```
输出如下:
```log
F: 23, 677, 4
J: 53, 233, 16
A: 2, 405, -6
Q: -12, 433, -42
Y: 95, 905, 3
B: 103, 376, -6
W: 14, 432, 23
X: -5, 445, -1
```
- 使用 `zip` 创建一个字段 `cast`,该字典使用 `names` 作为键,并使用 `heights` 作为值。
解决方案:
```python
cast_names = ["Barney", "Robin", "Ted", "Lily", "Marshall"]
cast_heights = [72, 68, 72, 66, 76]
cast = dict(zip(cast_names,cast_heights))
print(cast)
```
输出:
```log
{'Barney': 72, 'Ted': 72, 'Robin': 68, 'Lily': 66, 'Marshall': 76}
```
- 将 `cast` 元组拆封成两个 `names` 和 `heights` 元组。
解决方案:
```python
cast = (("Barney", 72), ("Robin", 68), ("Ted", 72), ("Lily", 66), ("Marshall", 76))
# define names and heights here
names,heights = zip(*cast)
print(names) # ('Barney', 'Robin', 'Ted', 'Lily', 'Marshall')
print(heights) # (72, 68, 72, 66, 76)
```
- 使用 `zip` 将 `data` 从 `4x3` 矩阵转置成 `3x4` 矩阵。
解决方案:
```python
data = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11))
data_transpose = tuple(zip(*data))
print(data_transpose) # ((0, 3, 6, 9), (1, 4, 7, 10), (2, 5, 8, 11))
```
- 使用 `enumerate` 修改列表 `cast`,使每个元素都包含姓名,然后是角色的对应身高。例如,`cast` 的第一个元素应该从 "Barney Stinson" 更改为 "Barney Stinson 72”。
解决方案:
```python
cast = ["Barney Stinson", "Robin Scherbatsky", "Ted Mosby", "Lily Aldrin", "Marshall Eriksen"]
heights = [72, 68, 72, 66, 76]
for i, c in enumerate(cast):
cast[i] += ' ' + str(heights[i])
print(cast) # ['Barney Stinson 72', 'Robin Scherbatsky 68', 'Ted Mosby 72', 'Lily Aldrin 66', 'Marshall Eriksen 76']
```
### 列表推导式
- 列表推导式可以快速简练地创建列表 <br>
之前的复杂写法:
```python
capitalized_cities = []
for city in cities:
capitalized_cities.append(city.title())
```
简化后的写法:<br>
```python
capitalized_cities = [city.title() for city in cities]
```
由此可见:借助列表推导式,我们可以使用 for 循环用一步创建一个列表。
- 列表推导式中的条件语句:
* 可以向列表推导式添加条件语句:`squares = [x**2 for x in range(9) if x % 2 == 0]`
* 如果你要添加 else,则需要将条件语句移到列表推导式的开头,直接放在表达式后面,如下:
* `squares = [x**2 if x % 2 == 0 else x + 3 for x in range(9)]`
* 注意:列表推导式并没有在其他语言中出现,但是在 python 中很常见。
### 列表推导式[相关练习]
- 使用列表推导式创建新的列表 first_names,其中仅包含 names 中的名字(小写形式)。
```python
names = ["Rick Sanchez", "Morty Smith", "Summer Smith", "Jerry Smith", "Beth Smith"]
first_names = [name.split(' ')[0].lower() for name in names]
print(first_names) # ['rick', 'morty', 'summer', 'jerry', 'beth']
```
- 使用列表推导式创建一个列表 multiples_3,其中包含 1-20 这20个整数的 3 的倍数。
```python
multiples_3 = [3 * num for num in range(1, 21)]
print(multiples_3) # [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60]
```
- 使用列表推导式创建一个 passed 的姓名列表,其中仅包含得分至少为 65 分的名字。
```python
scores = {
"Rick Sanchez": 70,
"Morty Smith": 35,
"Summer Smith": 82,
"Jerry Smith": 23,
"Beth Smith": 98
}
passed = [name for name, score in scores.items() if score >= 65]
print(passed) # ['Rick Sanchez', 'Beth Smith', 'Summer Smith']
```
### 学习链接
- https://anandology.com/python-practice-book/iterators.html