跳转到内容

面向非程序员的 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语句都打印一个数字和一个表达式。数字用于帮助跟踪我正在处理哪个语句。注意每个表达式最终都变成FalseTrue。在 Python 中,false 也可以写成 0,true 写成 1。

以下几行

print 1, a == 6
print 2, a == 7

分别打印出TrueFalse,正如预期的那样,因为第一个为真,第二个为假。第三个打印语句,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 == 7print 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

此时,andor运算符似乎坏了。对于前两个表达式,'a'等效于'a''b',而'b'则不是,这说不通。此外,'b'等效于'a''b',这也没有道理。在检查了解释器对布尔运算符的处理方式后,这些结果实际上完全符合您的要求,只是不符合您的预期。

当 Python 解释器查看or表达式时,它会取第一个语句,并检查它是否为真。如果第一个语句为真,则 Python 会返回该对象的 value,而无需检查第二个语句。这是因为对于or表达式,如果其中一个值为真,则整个表达式为真;程序不需要理会第二个语句。另一方面,如果第一个值被评估为假,则 Python 会检查第二部分并返回该值。第二部分决定整个表达式的真值,因为第一部分为假。解释器的这种“懒惰”被称为“短路”,是许多编程语言中评估布尔表达式的常用方法。

类似地,对于and表达式,Python 使用短路技术来加速真值评估。如果第一个语句为假,则整个表达式必须为假,因此它返回该值。否则,如果第一个值为真,则它会检查第二个值并返回该值。

需要注意的是,布尔表达式返回一个表示TrueFalse的值,但 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 + "!"
华夏公益教科书