面向非程序员的 Python 2.6 布尔表达式教程
这是一个布尔表达式的简单示例(您不必输入它)
a = 6
b = 7
c = 42
print 1, a == 6
print 2, a == 7
print 3, a == 6 and b == 7
print 4, a == 7 and b == 7
print 5, not a == 7 and b == 7
print 6, a == 7 or b == 7
print 7, a == 7 or b == 6
print 8, not (a == 7 and b == 6)
print 9, not a == 7 and b == 6
输出为
1 True 2 False 3 True 4 False 5 True 6 True 7 False 8 True 9 False
发生了什么?程序包含一堆看起来奇怪的print
语句。每个print
语句都打印一个数字和一个表达式。数字用于帮助跟踪我正在处理哪个语句。注意每个表达式最终都变成False
或True
。在 Python 中,false 也可以写成 0,true 写成 1。
以下几行
print 1, a == 6
print 2, a == 7
分别打印出True
和False
,正如预期的那样,因为第一个为真,第二个为假。第三个打印语句,print 3, a == 6 and b == 7
,有点不同。运算符and
表示如果前面和后面的语句都为真,则整个表达式为真,否则整个表达式为假。下一行,print 4, a == 7 and b == 7
,显示了如果and
表达式的一部分为假,则整个表达式为假。and
的行为可以总结如下
表达式 | 结果 |
---|---|
true and true |
true |
true and false |
false |
false and true |
false |
false and false |
false |
请注意,如果第一个表达式为假,Python 不会检查第二个表达式,因为它知道整个表达式为假。
下一行,print 5, not a == 7 and b == 7
,使用了not
运算符。not
只是给出表达式的相反结果。(该表达式可以改写为 print 5, a != 7 and b == 7
)。以下是表格
表达式 | 结果 |
---|---|
not true |
false |
not false |
true |
接下来的两行,print 6, a == 7 or b == 7
和print 7, a == 7 or b == 6
,使用了or
运算符。or
运算符如果第一个表达式为真,或第二个表达式为真,或两者都为真,则返回真。如果两者都不为真,则返回假。以下是表格
表达式 | 结果 |
---|---|
true or true |
true |
true or false |
true |
false or true |
true |
false or false |
false |
请注意,如果第一个表达式为真,Python 不会检查第二个表达式,因为它知道整个表达式为真。这是有效的,因为or
至少有一半表达式为真时就为真。第一部分为真,所以第二部分可以是假或真,但整个表达式仍然为真。
接下来的两行,print 8, not (a == 7 and b == 6)
和print 9, not a == 7 and b == 6
,显示了括号可以用来分组表达式,并强制先评估一部分。注意括号将表达式从假变为真。这是因为括号强制not
应用于整个表达式,而不是仅仅应用于a == 7
部分。
以下是如何使用布尔表达式的示例
list = ["Life", "The Universe", "Everything", "Jack", "Jill", "Life", "Jill"]
# make a copy of the list. See the More on Lists chapter to explain what [:] means.
copy = list[:]
# sort the copy
copy.sort()
prev = copy[0]
del copy[0]
count = 0
# go through the list searching for a match
while count < len(copy) and copy[count] != prev:
prev = copy[count]
count = count + 1
# If a match was not found then count can't be < len
# since the while loop continues while count is < len
# and no match is found
if count < len(copy):
print "First Match:", prev
以下是输出
First Match: Jill
该程序通过不断检查匹配项来工作,while count < len(copy) and copy[count] is not equal to prev
。当count
大于copy
的最后一个索引或找到匹配项时,and
不再为真,所以循环退出。if
只是检查确保while
退出是因为找到了匹配项。
本例中使用了and
的另一个“技巧”。如果您查看and
的表格,注意第三个条目是“false and won't check”。如果count >= len(copy)
(换句话说,count < len(copy)
为假),则不会查看copy[count]
。这是因为 Python 知道,如果第一个为假,则它们不可能都为真。这被称为短路,在第二部分and
可能会导致错误的情况下非常有用。我使用第一个表达式(count < len(copy)
)来检查count
是否是copy
的有效索引。(如果您不相信我,请删除匹配项“Jill”和“Life”,检查它是否仍然有效,然后反转count < len(copy) and copy[count] != prev
的顺序,使其成为copy[count] != prev and count < len(copy)
)。
当您需要一次检查两个或更多不同的事情时,可以使用布尔表达式。
初学编程的人常犯的一个错误是对布尔运算符工作方式的误解,这源于 Python 解释器读取这些表达式的 방식。例如,在初步学习“and”和“or”语句后,人们可能会认为表达式x == ('a' or 'b')
会检查变量x
是否等效于字符串'a'
或'b'
中的一个。事实并非如此。要了解我的意思,请启动与解释器的交互会话,并输入以下表达式
>>> 'a' == ('a' or 'b') >>> 'b' == ('a' or 'b') >>> 'a' == ('a' and 'b') >>> 'b' == ('a' and 'b')
这将得到非直观的結果
>>> 'a' == ('a' or 'b') True >>> 'b' == ('a' or 'b') False >>> 'a' == ('a' and 'b') False >>> 'b' == ('a' and 'b') True
此时,and
和or
运算符似乎坏了。对于前两个表达式,'a'
等效于'a'
或'b'
,而'b'
则不是,这说不通。此外,'b'
等效于'a'
和'b'
,这也没有道理。在检查了解释器对布尔运算符的处理方式后,这些结果实际上完全符合您的要求,只是不符合您的预期。
当 Python 解释器查看or
表达式时,它会取第一个语句,并检查它是否为真。如果第一个语句为真,则 Python 会返回该对象的 value,而无需检查第二个语句。这是因为对于or
表达式,如果其中一个值为真,则整个表达式为真;程序不需要理会第二个语句。另一方面,如果第一个值被评估为假,则 Python 会检查第二部分并返回该值。第二部分决定整个表达式的真值,因为第一部分为假。解释器的这种“懒惰”被称为“短路”,是许多编程语言中评估布尔表达式的常用方法。
类似地,对于and
表达式,Python 使用短路技术来加速真值评估。如果第一个语句为假,则整个表达式必须为假,因此它返回该值。否则,如果第一个值为真,则它会检查第二个值并返回该值。
需要注意的是,布尔表达式返回一个表示True
或False
的值,但 Python 认为许多不同的事物都有真值。要检查任何给定对象x
的真值,可以使用函数bool(x)
来查看其真值。以下是一些对象真值示例的表格
True | False |
---|---|
True | False |
1 | 0 |
非零数字 | 字符串 'None' |
非空字符串 | 空字符串 |
非空列表 | 空列表 |
非空字典 | 空字典 |
现在可以理解我们在之前测试那些布尔表达式时得到的令人费解的结果了。让我们看看解释器在执行代码时的“看法”
第一种情况
>>> 'a' == ('a' or 'b') # Look at parentheses first, so evaluate expression "('a' or 'b')" # 'a' is a nonempty string, so the first value is True # Return that first value: 'a' >>> 'a' == 'a' # the string 'a' is equivalent to the string 'a', so expression is True True
第二种情况
>>> 'b' == ('a' or 'b') # Look at parentheses first, so evaluate expression "('a' or 'b')" # 'a' is a nonempty string, so the first value is True # Return that first value: 'a' >>> 'b' == 'a' # the string 'b' is not equivalent to the string 'a', so expression is False False
第三种情况
>>> 'a' == ('a' and 'b') # Look at parentheses first, so evaluate expression "('a' and 'b')" # 'a' is a nonempty string, so the first value is True, examine second value # 'b' is a nonempty string, so second value is True # Return that second value as result of whole expression: 'b' >>> 'a' == 'b' # the string 'a' is not equivalent to the string 'b', so expression is False False
第四种情况
>>> 'b' == ('a' and 'b') # Look at parentheses first, so evaluate expression "('a' and 'b')" # 'a' is a nonempty string, so the first value is True, examine second value # 'b' is a nonempty string, so second value is True # Return that second value as result of whole expression: 'b' >>> 'b' == 'b' # the string 'b' is equivalent to the string 'b', so expression is True True
因此,Python 在给出那些看似错误的结果时,实际上是在认真地执行任务。如前所述,重要的是要认识到布尔表达式在评估时的返回值,因为它并不总是显而易见的。
回到那些最初的表达式,以下是如何编写它们,使它们的行为符合您的预期
>>> 'a' == 'a' or 'a' == 'b' True >>> 'b' == 'a' or 'b' == 'b' True >>> 'a' == 'a' and 'a' == 'b' False >>> 'b' == 'a' and 'b' == 'b' False
当这些比较被评估时,它们会以 True 或 False 的形式返回真值,而不是字符串,因此我们得到了正确的结果。
password1.py
## This programs asks a user for a name and a password.
# It then checks them to make sure the user is allowed in.
name = raw_input("What is your name? ")
password = raw_input("What is the password? ")
if name == "Josh" and password == "Friday":
print "Welcome Josh"
elif name == "Fred" and password == "Rock":
print "Welcome Fred"
else:
print "I don't know you."
示例运行
What is your name? Josh What is the password? Friday Welcome Josh
What is your name? Bill What is the password? Money I don't know you.
编写一个程序,让用户猜您的名字,但他们只有 3 次机会,否则程序会退出。
编写一个程序,让用户猜您的名字,但他们只有 3 次机会,否则程序会退出。
print "Try to guess my name!"
count = 3
name = "Tony"
guess = raw_input("What is my name? ")
while count > 1 and guess != name:
print "You are wrong!"
guess = raw_input("What is my name? ")
count = count - 1
if guess != name:
print "You are wrong!" # this message isn't printed in the third chance, so we print it now
print "You ran out of chances."
quit
else:
print "Yes! My name is", name + "!"