条件、循环及其他语句
5.3 代码块:缩进的乐趣
5.4.6 更复杂的条件
15 6 7 8 9 10 11 12 13 14
还有一个与if语句很像的“亲戚”,它就是条件表达式——C语言中三目运算符的Python版本。
下面的表达式使用if和else确定其值:
status = "friend" if name.endswith("Gumby") else "stranger"
如果条件(紧跟在if后面)为真,表达式的结果为提供的第一个值(这里为"friend"),否 则为第二个值(这里为"stranger")。
5.4.4 elif 子句
要检查多个条件,可使用elif。elif是else if的缩写,由一个if子句和一个else子句组合而 成,也就是包含条件的else子句。
num = int(input('Enter a number: ')) if num > 0:
print('The number is positive') elif num < 0:
print('The number is negative') else:
print('The number is zero')
5.4.5 代码块嵌套
下面穿插点额外的内容。你可将if语句放在其他if语句块中,如下所示:
name = input('What is your name? ') if name.endswith('Gumby'):
if name.startswith('Mr.'):
print('Hello, Mr. Gumby') elif name.startswith('Mrs.'):
print('Hello, Mrs. Gumby') else:
print('Hello, Gumby') else:
print('Hello, stranger')
在这里,如果名字以Gumby结尾,就同时检查名字开头,这是在第一个代码块中使用一条独 立的if语句完成的。请注意,这里还使用了elif。最后一个分支(else子句)没有指定条件——
如果没有选择其他分支,就选择最后一个分支。如果需要,这里的两个else子句都可省略。如果 省略里面的else子句,将忽略并非以Mr.或Mrs.打头的名字(假设名字为Gumby)。如果省略外面 的else子句,将忽略陌生人。
5.4.6 更复杂的条件
这就是你需要知道的有关if语句的全部知识。下面来说说条件本身,因为它们是有条件执行 中最有趣的部分。
1. 比较运算符
在条件表达式中,最基本的运算符可能是比较运算符,它们用于执行比较。表5-1对比较运 算符做了总结。
表5-1 Python比较运算符
表 达 式 描 述
x == y x 等于y
x < y x小于y
x > y x大于y
x >= y x大于或等于y
x <= y x小于或等于y
x != y x不等于y
x is y x和y是同一个对象
x is not y x和y是不同的对象
x in y x是容器(如序列)y的成员
x not in y x不是容器(如序列)y的成员
对不兼容的类型进行比较
从理论上说,可使用<和<=等运算符比较任意两个对象x和y的相对大小,并获得一个真 值,但这种比较仅在x和y的类型相同或相近时(如两个整数或一个整数和一个浮点数)才有 意义。
将整数与字符串相加毫无意义,检查一个整数是否小于一个字符串也是一样。奇怪的 是,在Python 3之前,竟然可以这样做。不过即便你使用的是较旧的Python版本,也应对这类 比较敬而远之,因为结果是不确定的,每次执行程序时都可能不同。在Python 3中,已经不允 许这样比较不兼容的类型了。
与赋值一样,Python也支持链式比较:可同时使用多个比较运算符,如0 < age < 100。 有些比较运算符需要特别注意,下面就来详细介绍。
相等运算符
要确定两个对象是否相等,可使用比较运算符,用两个等号(==)表示。
>>> "foo" == "foo"
True
>>> "foo" == "bar"
False
两个等号?为何不像数学中那样使用一个等号呢?相信你很聪明,自己就能够明白其中的原 因,但这里还是试试一个等号吧。
>>> "foo" = "foo"
SyntaxError: can't assign to literal
1
>>> y.reverse()
在这个示例中,我首先创建了两个不同的列表x和y。如你所见,x is not y(与x is y相反)
name = input('What is your name?') if 's' in name:
print('Your name contains the letter "s".') else:
print('Your name does not contain the letter "s".')
字符串和序列的比较
字符串是根据字符的字母排列顺序进行比较的。
>>> "alpha" < "beta"
True
虽然基于的是字母排列顺序,但字母都是Unicode字符,它们是按码点排列的。
>>> " " < " "
True
实际上,字符是根据顺序值排列的。要获悉字母的顺序值,可使用函数ord。这个函数的作 用与函数chr相反:
>>> ord(" ") 128585
>>> ord(" ") 128586
>>> chr(128584) ' '
这种方法既合理又一致,但可能与你排序的方式相反。例如,涉及大写字母时,排列顺序就 可能与你想要的不同。
>>> "a" < "B"
False
一个诀窍是忽略大小写。为此可使用字符串方法lower,如下所示(参见第3章):
>>> "a".lower() < "B".lower() True
>>> 'FnOrD'.lower() == 'Fnord'.lower() True
其他序列的比较方式与此相同,但这些序列包含的元素可能不是字符,而是其他类型的值。
>>> [1, 2] < [2, 1]
True
如果序列的元素为其他序列,将根据同样的规则对这些元素进行比较。
>>> [2, [1, 4]] < [2, [1, 5]]
True
2. 布尔运算符
至此,你已见过很多返回真值的表达式(实际上,考虑到所有值都可解释为真值,因此所有 的表达式都返回真值),但你可能需要检查多个条件。例如,假设你要编写一个程序,让它读取 一个数,并检查这个数是否位于1~10(含)。为此,可像下面这样做:
number = int(input('Enter a number between 1 and 10: ')) if number <= 10:
1 2 3 4 5
15 6 7 8 9 10 11 12 13 14
if number >= 1:
print('Great!') else:
print('Wrong!') else:
print('Wrong!')
这可行,但有点笨拙,因为你输入了print('Wrong!')两次。重复劳动可不是好事,那么该如 何办呢?很简单。
number = int(input('Enter a number between 1 and 10: ')) if number <= 10 and number >= 1:
print('Great!') else:
print('Wrong!')
注意 通过使用链式比较1 <= number <= 10可进一步简化这个示例。也许原本就应该这样做。
运算符and是一个布尔运算符。它接受两个真值,并在这两个值都为真时返回真,否则返回 假。还有另外两个布尔运算符:or和not。通过使用这三个运算符,能以任何方式组合真值。
if ((cash > price) or customer_has_good_credit) and not out_of_stock:
give_goods()
短路逻辑和条件表达式
布尔运算符有个有趣的特征:只做必要的计算。例如,仅当x和y都为真时,表达式x and y才为真。因此如果x为假,这个表达式将立即返回假,而不关心y。实际上,如果x为假,这 个表达式将返回x,否则返回y。(这将提供预期的结果,你明白了其中的原理吗?)这种行为 称为短路逻辑(或者延迟求值):布尔运算符常被称为逻辑运算符,如你所见,在有些情况下 将“绕过”第二个值。对于运算符or,情况亦如此。在表达式x or y中,如果x为真,就返回 x,否则返回y。(你明白这样做合理的原因吗?)请注意,这意味着位于布尔运算符后面的代 码(如函数调用)可能根本不会执行。像下面这样的代码就利用了这种行为:
name = input('Please enter your name: ') or '<unknown>'
如果没有输入名字,上述or表达式的结果将为'<unknown>'。在很多情况下,你都宁愿使 用条件表达式,而不耍这样的短路花样。不过前面这样的语句确实有其用武之地。
5.4.7 断言
if语句有一个很有用的“亲戚”,其工作原理类似于下面的伪代码:
if not condition:
crash program
问题是,为何要编写类似于这样的代码呢?因为让程序在错误条件出现时立即崩溃胜过以后
再崩溃。基本上,你可要求某些条件得到满足(如核实函数参数满足要求或为初始测试和调试提 供帮助),为此可在语句中使用关键字assert。
>>> age = 10
>>> assert 0 < age < 100
>>> age = -1
>>> assert 0 < age < 100
Traceback (most recent call last):
File "<stdin>", line 1, in ? AssertionError
如果知道必须满足特定条件,程序才能正确地运行,可在程序中添加assert语句充当检查点,
这很有帮助。
还可在条件后面添加一个字符串,对断言做出说明。
>>> age = -1
>>> assert 0 < age < 100, 'The age must be realistic' Traceback (most recent call last):
File "<stdin>", line 1, in ?
AssertionError: The age must be realistic
5.5 循环
至此,你知道了如何在条件为真(或假)时执行操作,但如何重复操作多次呢?例如,你可 能想创建一个程序,每月都提醒支付房租。如果只使用已介绍过的工具,必须像下面这样编写这 个程序(伪代码):
send mail
wait one month send mail wait one month send mail wait one month
(... and so on)
但是如果希望程序这样不断执行下去,直到人为停止,该如何办呢?基本上,你需要编写类 似于下面的代码(也是伪代码):
while we aren't stopped:
send mail wait one month
再来看一个更简单的例子,假设要打印1~100的所有数。同样,你可采用笨办法。
print(1) print(2) print(3) ...
print(99) print(100)
但如果你愿意使用笨办法,就不会求助于Python了,不是吗?