条件语句

在许多情况下,行动和结果取决于一组特定条件是否满足。例如,随机对照试验中的个体如果被分配到治疗组则接受治疗。赌徒如果赢了赌注就能赚钱。

在本节中,我们将学习如何使用代码描述这类情况。“条件语句”是一种多行语句,它允许 Python 根据表达式的真假值在不同选项之间进行选择。虽然条件语句可以出现在任何地方,但它们最常见于函数体内部,用于根据参数值表达不同的行为。

条件语句总是以 if 开头,这是一个单行,后跟一个缩进的主体。只有当紧跟在 if 后面的表达式(称为“if 表达式”)求值为真值时,主体才会被执行。如果“if 表达式”求值为假值,则跳过 if 的主体。

让我们开始定义一个返回数字符号的函数。

[In ]:
from datascience import *
path_data = '../../../assets/data/'
import matplotlib
matplotlib.use('Agg')
%matplotlib inline
import matplotlib.pyplot as plots
plots.style.use('fivethirtyeight')
import numpy as np
[In ]:
def sign(x):
    
    if x > 0:
        return 'Positive'
[In ]:
sign(3)
'Positive'

如果输入是正数,这个函数返回正确的符号。但如果输入不是正数,那么“if 表达式”求值为假值,因此 return 语句被跳过,函数调用没有返回值。

[In ]:
sign(-3)

因此,让我们改进我们的函数,使它在输入为负数时返回 Negative。我们可以通过添加一个 elif 子句来实现,其中 elif 是 Python 中“else, if”的简写。

[In ]:
def sign(x):
    
    if x > 0:
        return 'Positive'
    
    elif x < 0:
        return 'Negative'

现在当输入为 -3 时,sign 返回正确的答案:

[In ]:
sign(-3)
'Negative'

如果输入是 0 呢?为了处理这种情况,我们可以添加另一个 elif 子句:

[In ]:
def sign(x):
    
    if x > 0:
        return 'Positive'
    
    elif x < 0:
        return 'Negative'
    
    elif x == 0:
        return 'Neither positive nor negative'
[In ]:
sign(0)
'Neither positive nor negative'

等价地,我们可以将最后的 elif 子句替换为 else 子句,其主体仅在所有先前的比较都为假时才执行;也就是说,如果输入值等于 0。

[In ]:
def sign(x):
    
    if x > 0:
        return 'Positive'
    
    elif x < 0:
        return 'Negative'
    
    else:
        return 'Neither positive nor negative'
[In ]:
sign(0)
'Neither positive nor negative'

一般形式

条件语句也可以有多个子句和多个主体,并且这些主体中只能有一个被执行。多子句条件语句的一般格式如下。

if <if 表达式>:
    <if 主体>
elif <elif 表达式 0>:
    <elif 主体 0>
elif <elif 表达式 1>:
    <elif 主体 1>
...
else:
    <else 主体>

总是恰好有一个 if 子句,但可以有任意数量的 elif 子句。Python 将按顺序评估头部的 ifelif 表达式,直到找到一个真值,然后执行相应的主体。else 子句是可选的。当提供了 else 头部时,其“else 主体”仅当前面子句的所有头部表达式都不为真时才执行。else 子句必须始终放在最后(或者根本不使用)。

示例:掷骰子下注

假设我在掷一颗公平骰子上打赌。游戏规则:

  • 如果骰子显示 1 点或 2 点,我输一美元。
  • 如果骰子显示 3 点或 4 点,我不输不赢。
  • 如果骰子显示 5 点或 6 点,我赢一美元。

现在我们将使用条件语句定义一个函数 one_bet,它接受骰子的点数并返回我的净收益。

[In ]:
def one_bet(x):
    """Returns my net gain if the die shows x spots"""
    if x <= 2:
        return -1
    elif x <= 4:
        return 0
    elif x <= 6:
        return 1

让我们检查函数对每个不同点数的处理是否正确。

[In ]:
one_bet(1), one_bet(2), one_bet(3), one_bet (4), one_bet(5), one_bet(6)
(-1, -1, 0, 0, 1, 1)

作为条件语句工作原理的回顾,让我们看看当输入为 3 时 one_bet 做了什么。

  • 首先它评估 if 表达式,即 3 <= 2,结果为 False。因此 one_bet 不执行 if 主体。
  • 然后它评估第一个 elif 表达式,即 3 <= 4,结果为 True。因此 one_bet 执行第一个 elif 主体并返回 0。
  • 主体执行完毕后,过程结束。下一个 elif 表达式不被评估。

如果出于某种原因我们使用大于 6 的输入,那么 if 表达式和两个 elif 表达式都评估为 False。因此 one_bet 不执行 if 主体也不执行两个 elif 主体,下面的调用将没有返回值。

[In ]:
one_bet(17)

要基于一次掷骰子玩游戏,你可以使用 np.random.choice 生成点数,然后将其作为 one_bet 的参数。多次运行该单元格以查看输出如何变化。

[In ]:
one_bet(np.random.choice(np.arange(1, 7)))
-1

此时,很自然地希望收集所有下注的结果以便进行分析。在下一节中,我们将开发一种方法来实现这一点,而无需反复运行单元格。