条件语句、断言、循环
条件和条件语句
布尔值的用武之地便是条件语句。
用作布尔表达式(如用作if
语句中的条件)时,下面的值都将被解释器视为假:
False None 0 "" () [] {}
换而言之,标准值False
和None
、各种类型(包括浮点数、复数等)的数值0、空序列(如空字符串、空元组和空列表)以及空映射(如空字典)都被视为假,而其他各种值都被视为真,包括特殊值True
。
布尔值True
和False
属于类型bool
,而bool
与list
、str
和tuple
一样,可用来转换其他的值。
>>> bool('I think, therefore I am') True >>> bool(42) True >>> bool('') False >>> bool(0) False
鉴于任何值都可用作布尔值,因此你几乎不需要显式地进行转换(Python会自动转换)。
方法endswith()功能是检测最后输入的数值
name = input('What is your name? ') if name.endswith('Gumby'): print('Hello, Mr. Gumby')
如果你输入以Gumby结尾的名字,方法name.endswith
将返回True
,导致后续代码块执行——打印问候语。
还有一个与if
语句很像的“亲戚”,它就是条件表达式——C语言中三目运算符的Python版本。下面的表达式使用if
和else
确定其值:
status = "friend" if name.endswith("Gumby") else "stranger"
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 的成员 |
与赋值一样,Python也支持链式比较:可同时使用多个比较运算符,如0 < age < 100
。
有些比较运算符需要特别注意,下面就来详细介绍。
相等运算符:
要确定两个对象是否相等,可使用比较运算符,用两个等号(==
)表示。
>>> "foo" == "foo" True >>> "foo" == "bar" False
一个等号是赋值运算符,用于修改值。
is
:相同运算符
这个运算符很有趣,其作用看似与==
一样,但实际上并非如此。
>>> x = y = [1, 2, 3] >>> z = [1, 2, 3] >>> x == y True >>> x == z True >>> x is y True >>> x is z False
在前几个示例中,看不出什么问题,但最后一个示例的结果很奇怪:x
和z
相等,但x is z
的结果却为False
。为何会这样呢?因为is
检查两个对象是否相同(而不是相等)。变量x
和y
指向同一个列表,而z
指向另一个列表(其中包含的值以及这些值的排列顺序都与前一个列表相同)。这两个列表虽然相等,但并非同一个对象。
总之,==
用来检查两个对象是否相等,而is
用来检查两个对象是否相同(是同一个对象)。
警告 不要将is
用于数和字符串等不可变的基本值。鉴于Python在内部处理这些对象的方式,这样做的结果是不可预测的。
in:成员资格运算符
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字符,它们是按码点排列的。
实际上,字符是根据顺序值排列的。要获悉字母的顺序值,可使用函数ord
。这个函数的作用与函数chr
相反:
>>> ord("a") 97 >>> ord("b") 98 >>> chr(36) '$'
这种方法既合理又一致,但可能与你排序的方式相反。例如,涉及大写字母时,排列顺序就可能与你想要的不同。
>>> "a" < "B" False
一个诀窍是忽略大小写。为此可使用字符串方法lower.
>>> "a".lower() < "B".lower() True
其他序列的比较方式与此相同,但这些序列包含的元素可能不是字符,而是其他类型的值。
>>> [1, 2] < [2, 1]
True
如果序列的元素为其他序列,将根据同样的规则对这些元素进行比较。
>>> [2, [1, 4]] < [2, [1, 5]]
True
短路逻辑和条件表达式
布尔运算符有个有趣的特征:只做必要的计算。例如,仅当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>'
。在很多情况下,你都宁愿使用条件表达式,而不耍这样的短路花样。不过前面这样的语句确实有其用武之地。
断言
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
循环操作(while):
name = '' while not name: #没有名字为真将执行程序块 name = input('Please enter your name: ') print('Hello, {}!'.format(name))
请尝试运行这些代码,并在要求你输入名字时直接按回车键。你会看到提示信息再次出现,因为name
还是为空字符串,这相当于假。(not假 就是真)
提示 如果你只是输入一个空格字符(将其作为你的名字),结果将如何呢?试试看。程序将接受这个名字,因为包含一个空格字符的字符串不是空的,因此不会将name
视为假。这无疑是这个小程序的一个瑕疵,但很容易修复:只需将while not name
改为while not name or name.isspace()
或while not name.strip()
即可。
for循环:
words = ['this', 'is', 'an', 'ex', 'parrot'] for word in words: print(word)
鉴于迭代(也就是遍历)特定范围内的数是一种常见的任务,Python提供了一个创建范围的内置函数。
>>> range(0, 10) range(0, 10) >>> list(range(0, 10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
范围类似于切片。它们包含起始位置(这里为0),但不包含结束位置(这里为10)。在很多情况下,你都希望范围的起始位置为0。实际上,如果只提供了一个位置,将把这个位置视为结束位置,并假定起始位置为0。
>>> range(10)
range(0, 10)
下面的程序打印数1~100:
for number in range(1,101): print(number)
注意,相比前面使用的while
循环,这些代码要紧凑得多。
提示 只要能够使用
for
循环,就不要使用while
循环。