Python入门 - 第 2 节课:控制流

目录


1. 条件语句

  • If 语句

if语句是是一种条件语句,根据条件为 true 还是 false 运行或执行相关代码。下面是一个简单的示例:

if phone_balance < 5:
    phone_balance += 10
    bank_balance -= 10
  • 第一行: if 语句以关键字if 开始,然后是要检查的条件,在此例中是 phone_balance < 5,接着是英文冒号。条件用布尔表达式指定,结果为 TrueFalse
  • 第二, 三行: 这行之后是一个条件为 true 时将执行的缩进代码块。在此例中,仅在 phone_balance 小于 5 时才执行使 phone_balance 递增和使bank_balance 递减的行。如果不小于 5,这个 if 块中的代码将被跳过。

 

  • If、Elif、Else

除了 if条件之外,if语句经常还会使用另外两个可选条件。例如:

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')
  1. ifif 语句必须始终以if条件开始,其中包含第一个要检查的条件。如果该条件为 True,Python 将运行这个if块中的缩进代码,然后跳到 if 语句之后的剩余代码。
  2. elifelif条件用来检查其他条件(前提是if语句中之前的条件结果为 False)。可以从示例中看出,可以使用多个elif 块处理不同的情形。
  3. else:最后是else 条件,它必须位于if 语句的末尾。该条件语句不需要条件。如果if 语句中所有前面的语句结果都为False时,将运行 else 块中的代码。

 
 

2. 布尔表达式

If 语句有时候会使用更加复杂的条件布尔表达式。可能包括多个比较运算符、逻辑运算符,甚至包括算式。例如:

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")

对于非常复杂的条件,你可能需要结合使用andornot。使用括号可以使运算符组合更清晰。

无论是简单还是复杂的条件,if 语句中的条件都必须是结果为TrueFalse的布尔表达式,该值决定了if 语句中的缩进代码块是否执行。

注意事项
1. 请勿使用 True 或 False 作为条件

# Bad example
if True:
    print("This indented code will always get run.")

虽然“True”是一个有效的布尔表达式,但不是有用的条件,因为它始终为 True,因此缩进代码将始终运行。同样,if False 也不应使用,该 if语句之后的语句将从不运行。

# Another bad example
if is_cold or not is_cold:
    print("This indented code will always get run.")

同样,使用你知道将始终结果为 True 的条件(例如上述示例)也是毫无用途的。布尔表达式只能为 TrueFalse,因此is_coldnot is_cold将始终为 True,缩进代码将始终运行。

2. 在使用逻辑运算符编写表达式时,要谨慎
逻辑运算符 and、or 和 not 具有特定的含义,与字面英文意思不太一样。确保布尔表达式的结果和你预期的一样。

# Bad example
if weather == "snow" or "rain":
    print("Wear boots!")

这段代码在 Python 中是有效的,但不是布尔表达式,虽然读起来像。原因是 or 运算符右侧的表达式 "rain" 不是布尔表达式,它是一个字符串。

3. 请勿使用 == True 或 == False 比较布尔变量
这种比较没必要,因为布尔变量本身是布尔表达式。

# Bad example
if is_cold == True:
    print("The weather is cold!")

这是一个有效的条件,但是我们可以使用变量本身作为条件,使代码更容易读懂,如下所示。

# Good example
if is_cold:
    print("The weather is cold!")

如果你想检查布尔表达式是否为 False,可以使用 not 运算符。

真假值测试
如果我们在if 语句中使用非布尔对象代替布尔表达式,Python 将检查其真假值,判断是否运行缩进代码。默认情况下,Python 中对象的真假值被视为 True,除非在文档中被指定为 False。

以下是在 Python 中被视为 False 的大多数内置对象:

  • 定义为 false 的常量:NoneFalse
  • 任何数字类型的零:00.00jDecimal(0)Fraction(0, 1)
  • 空序列和空集合:””()[]{}set()range(0)

示例:

errors = 3
if errors:
    print("You have {} errors to fix!".format(errors))
else:
    print("No errors to fix!")

在上述代码中,errors 的真假值为 True,因为它是非零数字,因此输出了错误消息。这是一个编写 if 语句的简练方式。

 
 

3. For 和 While 循环

For循环

Python 有两种类型的循环:for 循环和 while 循环。for 循环用来遍历可迭代对象。

可迭代对象是每次可以返回其中一个元素的对象,包括字符串、列表和元组等序列类型,以及字典和文件等非序列类型。你还可以使用迭代器和生成器定义可迭代对象,
我们来了解下 for 循环的各个组成部分。请看下面的示例:

# 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 循环的组成部分

  1. 循环的第一行以关键字 for 开始,表示这是一个 for 循环
  2. 然后是 iteration_variable in iterable,表示正在被遍历的是可迭代的对象,并且用迭代变量表示当前正在被处理的可迭代对象的元素。在此示例中,迭代变量 city 在第一次迭代时将是“new york city”,在第二次迭代时将是“mountain view。
  3. for 循环头部始终以英文冒号 : 结束。
  4. for 循环头部之后的是在此 for 循环的每次迭代时运行的缩进代码块。在此块中,我们可以使用迭代变量访问当前正在被处理的元素的值。

你可以随意命名迭代变量。常见模式是为迭代变量和可迭代对象指定相同的名称,但是分别使用单复数形式(例如 'city' 和 'cities')

For循环创建和修改列表

  • 创建
    除了从列表中提取信息之外,你还可以使用 for 循环创建和修改列表。你可以在 for 循环的每次迭代时向新列表中添加元素,创建一个列表。如下所示。
# 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 本身的输出是一个 range 对象。我们可以通过将其转换为列表或在 for 循环中遍历它,查看 range 对象中的值集合。

    使用 range 函数为 cities 列表中的每个值生成索引。这样我们便可以使用 cities[index] 访问列表中的元素,以便直接修改 cities 列表中的值。

cities = ['new york city', 'mountain view', 'chicago', 'los angeles']

for index in range(len(cities)):
    cities[index] = cities[index].title()

虽然修改列表是 range 函数的一个用途,但是并非只有这一个用途。你将经常使用 rangefor 循环重复某个操作一定的次数。

for i in range(3):
    print("Hello!")

 

While循环

For 循环是一种“有限迭代”,意味着循环主体将运行预定义的次数。这与“无限迭代”循环不同,无限迭代循环是指循环重复未知次数,并在满足某个条件时结束,while 循环正是这种情况。下面是一个 while 循环的示例。

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。

循环的缩进主体应该至少修改测试表达式中的一个变量。如果测试表达式的值始终不变,就会变成无限循环!

 
 

4. Break 和 Continue

有时候我们需要更精准地控制何时循环应该结束,或者跳过某个迭代。在这些情况下,我们使用关键字breakcontinue,这两个关键字可以用于forwhile循环。

  • break 使循环终止
  • continue 跳过循环的一次迭代
    代码示例
fruit = ['orange', 'strawberry', 'apple']
foods = ['apple', 'apple', 'hummus', 'toast']

fruit_count = 0
for food in foods:
    if food not in fruit:
        print('NOT a fruit')
        continue
# 执行continue后, 后面的语句将不执行, 进行下一次迭代.
    fruit_count += 1
    print('Found a fruit')  

 
 

5. Zip 和 Enumerate

zip 和 enumerate 是实用的内置函数,可以在处理循环时用到。

Zip

zip 返回一个(将多个可迭代对象组合成一个元组序列)的迭代器。每个元组都包含所有可迭代对象中该位置的元素。例如,

list(zip(['a', 'b', 'c'], [1, 2, 3])) 
#将输出
 [('a', 1), ('b', 2), ('c', 3)]

正如 range()一样,我们需要将其转换为列表或使用循环进行遍历以查看其中的元素。

你可以如下所示地用 for 循环拆封每个元组

letters = ['a', 'b', 'c']
nums = [1, 2, 3]

for letter, num in zip(letters, nums):
    print("{}: {}".format(letter, num))

除了可以将两个列表组合到一起之外,还可以使用星号拆封列表

some_list = [('a', 1), ('b', 2), ('c', 3)]
letters, nums = zip(*some_list)

这样可以创建正如之前看到的相同 lettersnums 列表。

Enumerate

enumerate 是一个会返回元组迭代器的内置函数,这些元组包含列表的索引。当你需要在循环中获取可迭代对象的每个元素及其索引时,将经常用到该函数。

letters = ['a', 'b', 'c', 'd', 'e']
for i, letter in enumerate(letters):
    print(i, letter)

这段代码将输出:

0 a
1 b
2 c
3 d
4 e

练习

将列表组合成字典

cast_names = ["Barney", "Robin", "Ted", "Lily", "Marshall"]
cast_heights = [72, 68, 72, 66, 76]

cast = dict(zip(cast_names, cast_heights))
print(cast)

输出:
该输出中的元素顺序可能有变化,因为字典是无序的。

{'Lily': 66, 'Barney': 72, 'Marshall': 76, 'Ted': 72, 'Robin': 68}

拆封元组

cast = (("Barney", 72), ("Robin", 68), ("Ted", 72), ("Lily", 66), ("Marshall", 76))

names, heights = zip(*cast)
print(names)
print(heights)

输出:

('Barney', 'Robin', 'Ted', 'Lily', 'Marshall')
(72, 68, 72, 66, 76)

用 Zip 进行转置

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))

 
 

6. 列表推导式

在 Python 中,你可以使用列表推导式快速简练地创建列表

capitalized_cities = []
for city in cities:
    capitalized_cities.append(city.title())

可以简写为:

capitalized_cities = [city.title() for city in cities]

借助列表推导式,我们可以使用 for 循环用一步创建一个列表。

我们使用方括号[]创建列表推导式,括号里包含要对可迭代对象中的每个元素进行评估的条件。上述列表推导式对cities 中的每个元素city 调用 city.title(),以为新列表 capitalized_cities 创建每个元素。

列表推导式中的条件语句
还可以向列表推导式添加条件语句。在可迭代对象之后,你可以使用关键字 if 检查每次迭代中的条件。

squares = [x**2 for x in range(9) if x % 2 == 0]

上述代码将squares设为等于列表[0, 4, 16, 36, 64],因为仅在 x 为偶数时才评估 x 的 2 次幂。如果你想添加 else,将遇到语法错误。

squares = [x**2 for x in range(9) if x % 2 == 0 else x + 3]

如果你要添加 else,则需要将条件语句移到列表推导式的开头,直接放在表达式后面,如下所示。

squares = [x**2 if x % 2 == 0 else x + 3 for x in range(9)]

列表推导式并没有在其他语言中出现,但是在 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']

按得分过滤姓名

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)

输出:
该输出中的元素顺序可能有变化,因为字典是无序的。

['Beth Smith', 'Summer Smith', 'Rick Sanchez']
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容