在编程中,我们经常需要基于多个条件来做决策。例如,只有当若干条件同时 满足时,我们才执行某个操作。或者,当若干条件中任意一个 满足时,我们触发另一种操作。
为处理这些场景,Python 提供了一组逻辑运算符 – and、or、not。
在本教程中,我们将学习 Python 逻辑运算符的工作原理,以及如何在编程和数据科学中使用它们。请注意,我们将用大写的 AND、OR 和 NOT 来抽象表示这些运算符;而提到具体的 Python 关键字时,使用 and、or 和 not 这种写法。
如果您在寻找系统化的 Python 课程路径,可以查看这条包含六门课程的 Python Programming 技能路径。
在深入细节之前,先给赶时间的您一个非常简短的答案。
简短回答:什么是 Python 逻辑运算符?
Python 的逻辑运算符(and、or、not)是一些特殊关键字,它们在代码中起到连接词的作用,用于在单个表达式内连接并评估多个条件。
看看这个示例:
temperature = 25
is_sunny = True
if temperature > 20 and is_sunny:
print ( "It's a perfect day for a picnic!" )
技术支持
It's a perfect day for a picnic!
技术支持
这里,and 运算符确保仅当两个条件都满足时才打印消息:气温高于 20 度且是晴天。
再看一个使用 or 运算符的示例:
has_umbrella = False
if is_sunny or has_umbrella:
print ( "Let's go for a walk!" )
技术支持
Let's go for a walk!
技术支持
在这种情况下,只要要么 是晴天,要么 我们带了伞,我们就会出去散步。
最后,not 运算符会翻转条件的真值:
if not is_sunny:
print ( "Maybe we should stay indoors." )
技术支持
这里,只有在不是 晴天时才会打印消息。
逻辑运算符为我们提供了一种简洁而强大的方式来表达复杂条件,使程序能够基于多种因素做出决策。现在,让我们更深入地看看,先从 and 逻辑运算符开始。
Python:and 运算符
在布尔逻辑中,AND 运算比较两个值或表达式。只有当两个值都为 true 时才产生 true 的结果。如果其中一个或两个值为 false,AND 运算的结果就是 false。下面是 AND 的行为总结:
运算
输出值
true AND true
true
true AND false
false
false AND true
false
false AND false
false
我们可以用 Python 的 and 运算符重现这张真值表:
options = True, False
for a in options :
for b in options :
print ( f"{a} and {b} gives {a and b}" )
技术支持
True and True gives True
True and False gives False
False and True gives False
False and False gives False
技术支持
options 变量包含两个布尔值。嵌套的 for 循环两次遍历 options,以生成 True 和 False 的所有排列组合。
常见情况下,作为 and 操作数的表达式会包含比较或相等运算符:
names = "James" , "Bob" , "David" , "Jane" , "Kate" , "Mary"
for name in names :
if len ( name) < 5 and name[ 0 ] == "J" :
print ( name)
技术支持
Jane
技术支持
只有当名字少于五个字母且以 "J" 开头时才会打印。两个条件都必须满足。
比较和相等运算符(如 < 和 ==)的结果为 True 或 False。
不过,Python 的 and 运算符可作用于任意数据类型,而不只是布尔值 True 和 False。其输出也可以是任意数据类型。
本节我们将更详细地探究 Python 的 and 运算符。首先讨论「真值性」。
Python:truthy 与 falsy
每个 Python 对象都可以用内置的 bool() 转换为布尔类型。如果 bool(object) 返回 True,该对象为 truthy;如果返回 False,则为 falsy。
Python 的 and 运算符会查看其操作数的真值性。如果两个操作数都为 truthy,and 也会返回一个 truthy 值;如果有一个或两个为 falsy,and 返回一个 falsy 值。看几个例子:
if 42 and "python" :
print ( "Both operands are truthy" )
else :
print ( "One or both operands are falsy" ) 技术支持
Both operands are truthy技术支持
再来看这个示例:
if 42 and "" :
print ( "Both operands are truthy" )
else :
print ( "One or both operands are falsy" )
技术支持
One or both operands are falsy技术支持
最后看这个示例:
if 0 and "python" :
print ( "Both operands are truthy" )
else :
print ( "One or both operands are falsy" ) 技术支持
One or both operands are falsy技术支持
数值类型(如整数、浮点数)在非零时为 truthy,等于零时为 falsy。序列类型(如字符串)在非空时为 truthy,空时为 falsy。
因此,上述三个示例中,只有第一个满足 and 运算符要求的「两个操作数都为 truthy」,从而评估为 truthy。
and 运算符并不总是返回布尔值。包含 and 的表达式也可能直接评估为某个操作数。我们用刚才的示例更深入地看看。与其放在 if 里,不如直接求值:
print ( 42 and "python" )
print ( 42 and "" )
print ( 0 and "python" )
技术支持
python
0技术支持
能看出这些表达式发生了什么吗?
先说第三个示例,两个操作数是 0 和 "python"。and 需要两个 truthy 操作数。由于第一个是 0,它是 falsy,因此无需检查第二个操作数,因为无论第二个值如何,整个表达式都将是 falsy。
不过,and 运算符并不会返回 False,而是直接返回第一个操作数。由于第一个操作数是 falsy,整个 and 表达式的真值性为 falsy。在 Python 中这不会有问题,因为在需要真或假值的上下文中,Python 会使用对象的真值性。
在第一个示例中,第一个操作数 42 为 truthy。程序会再评估第二个操作数并返回它。第二个操作数是字符串 "python",它是 truthy,因此整个表达式评估为 truthy。
在第二个示例中,第一个操作数同样是 42。由于它是 truthy,程序会评估并返回第二个操作数,即空字符串。空字符串为 falsy,因此整个 and 表达式评估为 falsy。
当第一个操作数为 truthy 时,and 运算符总是返回第二个操作数的值,不管第二个操作数是 truthy 还是 falsy。
当第一个操作数为 falsy 时,Python 不会再评估第二个操作数。这称为短路 ,是一种惰性求值。您可以用下面的代码验证:
0 and 5 / 0
技术支持
0
技术支持
第二个操作数是 5/0,通常会抛出 ZeroDivisionError。但在这个示例中,由于第一个操作数是 falsy,表达式 5/0 不会被求值,因此不会抛出异常。
示例:程序员的网上商店
接下来看一个贴近实际应用的简单示例。为程序员提供商品的网店,其交易通过 API 记录并访问。数据被转换为字典构成的列表。列表中的每个元素代表一条交易记录,每条交易都是一个包含相关信息的字典:
data = [
{ "Item" : "Python Book" , "Price" : 50 , "Quantity" : 1 , "Success" : True} ,
{ "Item" : "Coffee Machine" , "Price" : 125 , "Quantity" : 1 , "Success" : False} ,
{ "Item" : "Headphones" , "Price" : 250 , "Quantity" : 1 , "Success" : True} ,
{ "Item" : "Cables" , "Price" : 15.99 , "Quantity" : 3 , "Success" : True} ,
]
技术支持
每笔交易都包含商品名称与价格、订单数量,以及交易是否成功。
假设我们需要价格不低于 100 美元且交易成功的记录。可以使用 and 运算符来筛选所需行:
for item in data :
if item[ "Success" ] and item[ "Price" ] >= 100 :
print ( item) 技术支持
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True}技术支持
输出显示只有一条交易同时满足两个条件。对于交易列表中的每个条目,if 语句会检查两个表达式的真值性:
每个字典中键 "Success" 对应的值要么是 True,要么是 False。
item["Price"] >= 100 中的「大于等于」运算也返回 True 或 False。
Python 书和数据线不满足价格要求(均低于 100 美元)。咖啡机价格超过该阈值,但交易未成功,因此未被打印。
稍后我们会回到这个网店示例。
下一节将关注 or 运算符。
Python:or 运算符
在布尔逻辑中,OR 逻辑运算符需要两个操作数。只要至少一个操作数为 true ,其结果就为 true :
运算
输出值
true OR true
true
true OR false
true
false OR true
true
false OR false
false
我们可以用 Python 的 or 运算符重现这张真值表:
options = True, False
for a in options :
for b in options :
print ( f"{a} or {b} gives {a or b}" )
技术支持
True or True gives True
True or False gives True
False or True gives True
False or False gives False
技术支持
我们也可以回到之前的人名示例,但把 and 换成 or:
names = "James" , "Bob" , "David" , "Jane" , "Kate" , "Mary"
for name in names :
if len ( name) < 5 or name[ 0 ] == "J" :
print ( name)
技术支持
James
Bob
Jane
Kate
Mary
技术支持
现在 if 语句包含一个 or 表达式。因此,for 循环会打印所有要么少于五个字母,要么以字母 "J" 开头的名字。字符串 "Jane" 同时满足两个条件;其他被打印的名字满足其中一个条件。
Python or 运算符:truthy 与 falsy
or 运算符同样基于 truthy 和 falsy 值,而不仅仅是布尔值 True 与 False。来看一些示例:
if 42 or [ 10 , 20 , 30 ] :
print ( "At least one operand is truthy" )
else :
print ( "None of the operands is truthy" )
技术支持
At least one operand is truthy
技术支持
再看这个示例:
if 42 or [ ] :
print ( "At least one operand is truthy" )
else :
print ( "None of the operands is truthy" )
技术支持
At least one operand is truthy技术支持
最后再看这个示例:
if 0 or [ ] :
print ( "At least one operand is truthy" )
else :
print ( "None of the operands is truthy" )
技术支持
None of the operands is truthy
技术支持
在第一个示例中,整数 42 和非空列表 [10, 20, 30] 都是 truthy。由于 or 只需至少一个操作数为 truthy,整个表达式评估为 truthy。
在第二个示例中,42 是 truthy,而空列表 [] 是 falsy(因为它是空序列)。两个操作数中至少有一个为 truthy,因此整个 or 表达式评估为 truthy。
在最后一个示例中,0 和 [] 都是 falsy,因此整个表达式评估为 falsy。
or 运算符在评估表达式时也会使用短路,以避免不必要的求值。下面的示例可以说明这一点:
print ( 42 or [ 10 , 20 , 30 ] )
print ( 42 or [ ] )
print ( [ ] or 42 )
print ( [ ] or 0 )
技术支持
42
42
42
0
技术支持
在第一个示例中,第一个操作数 42 是 truthy。由于 or 只需要一个 truthy 操作数即可确定整个表达式的真值性,因此会立即返回第一个操作数。第二个操作数不会被求值,因为其值不影响最终结果。or 返回的是第一个操作数 42,而不是布尔值 True。在 Python 中,在 if 和 while 等语境下,任何 truthy 值都与布尔值 True 具有相同效果。
在第二个示例中,第一个操作数同样是 42,即便第二个操作数是 falsy,表达式仍返回该整数。
在第三和第四个示例中,第一个操作数是空列表(falsy),因此都会返回第二个操作数。
示例:程序员的网上商店
让我们回到向程序员销售商品的网店交易记录。以下是本例使用的四笔示例交易:
data = [
{ "Item" : "Python Book" , "Price" : 50 , "Quantity" : 1 , "Success" : True} ,
{ "Item" : "Coffee Machine" , "Price" : 125 , "Quantity" : 1 , "Success" : False} ,
{ "Item" : "Headphones" , "Price" : 250 , "Quantity" : 1 , "Success" : True} ,
{ "Item" : "Cables" , "Price" : 15.99 , "Quantity" : 3 , "Success" : True} ,
]
技术支持
您需要挑出一些交易,以便进一步研究客户行为。您想找出那些交易失败的,或包含价格低于 75 美元商品的交易。由于有两个条件且只需要满足其一,您可以使用 or 运算符:
for item in data :
if item[ "Success" ] == False or item[ "Price" ] < 75 :
print ( item)
技术支持
{ 'Item' : 'Python Book' , 'Price' : 50 , 'Quantity' : 1 , 'Success' : True}
{ 'Item' : 'Coffee Machine' , 'Price' : 125 , 'Quantity' : 1 , 'Success' : False}
{ 'Item' : 'Cables' , 'Price' : 15.99 , 'Quantity' : 3 , 'Success' : True}
技术支持
这个 for 循环会显示满足至少一个条件的行。Python 书和数据线因价格低于 75 美元而被包含;咖啡机因交易未成功而被包含。
对于筛选未成功的交易,还有另一种方式,下一节我们将探讨。
Python:not 运算符
NOT 运算符不同于 AND 和 OR,它只需要一个操作数。NOT 会把 true 变为 false,反之亦然。下面是 NOT 的真值表:
运算
输出值
NOT true
false
NOT false
true
我们可以用 Python 的 not 运算符来复现:
options = True, False
for a in options :
print ( f"not {a} evaluates to {not a}" )
技术支持
not True evaluates to False
not False evaluates to True
技术支持
Python not 运算符:truthy 与 falsy
与 and 和 or 一样,not 的操作数也不必是布尔值。由于任意对象要么为 truthy,要么为 falsy,因此任意对象都可以与 not 一起使用。
if not "python" :
print ( "The `if` statement evaluated as `True`" )
else :
print ( "The `if` statement evaluated as `False`" )
技术支持
The ` if ` statement evaluated as ` False ` 技术支持
再看这个示例:
if not "" :
print ( "The `if` statement evaluated as `True`" )
else :
print ( "The `if` statement evaluated as `False`" )
技术支持
The ` if ` statement evaluated as ` True `
技术支持
使用 not 时,truthy 值会被转换为 False,falsy 值会被转换为 True。
与 and 和 or 不同,not 运算符总是返回一个布尔对象:
print ( not "python" )
print ( not "" )
技术支持
False
True
技术支持
示例:程序员的网上商店
在前面的部分,我们使用了网店的交易记录。在这个示例中,我们想要显示所有未成功的交易。一种做法是使用相等运算符 == 检查 data["Success"] 是否等于 False。不过,我们也可以使用 not 运算符:
data = [
{ "Item" : "Python Book" , "Price" : 50 , "Quantity" : 1 , "Success" : True} ,
{ "Item" : "Coffee Machine" , "Price" : 125 , "Quantity" : 1 , "Success" : False} ,
{ "Item" : "Headphones" , "Price" : 250 , "Quantity" : 1 , "Success" : True} ,
{ "Item" : "Cables" , "Price" : 15.99 , "Quantity" : 3 , "Success" : True} ,
]
for item in data :
if not item[ "Success" ] :
print ( item)
技术支持
{ 'Item' : 'Coffee Machine' , 'Price' : 125 , 'Quantity' : 1 , 'Success' : False}
技术支持
由于未成功交易的 item["Success"] 等于 False,因此 not item["Success"] 返回 True。于是 for 循环会打印未成功的交易:
下一节我们将学习如何在一个表达式中组合多个逻辑运算符。
Python:运算符优先级
到目前为止的示例中,每次只使用了一个逻辑运算符。本节将看看在单个表达式中组合多个逻辑运算符时会发生什么。
Python:and 的优先级高于 or
我们继续使用之前的网店交易。来试试下面的条件语句:
data = [
{ "Item" : "Python Book" , "Price" : 50 , "Quantity" : 1 , "Success" : True} ,
{ "Item" : "Coffee Machine" , "Price" : 125 , "Quantity" : 1 , "Success" : False} ,
{ "Item" : "Headphones" , "Price" : 250 , "Quantity" : 1 , "Success" : True} ,
{ "Item" : "Cables" , "Price" : 15.99 , "Quantity" : 3 , "Success" : True} ,
]
for item in data :
if item[ "Price" ] > 100 or item[ "Quantity" ] > 2 and item[ "Success" ] :
print ( item)
技术支持
{ 'Item' : 'Coffee Machine' , 'Price' : 125 , 'Quantity' : 1 , 'Success' : False}
{ 'Item' : 'Headphones' , 'Price' : 250 , 'Quantity' : 1 , 'Success' : True}
{ 'Item' : 'Cables' , 'Price' : 15.99 , 'Quantity' : 3 , 'Success' : True}
技术支持
if 语句包含两个逻辑运算符。在研究 Python 如何处理这个表达式之前,我们先把它翻译成一句英文描述:如果商品价格超过 100 美元,或者售出数量大于 2 且交易成功,则打印该条目。
如果不加更多标点,这句话是有歧义的;即便加了更多逗号,也可能让人困惑。比如,是否应包含咖啡机的那笔交易?它的价格超过阈值,但交易并不成功。
Python 通过赋予 and 高于 or 的优先级来消除这种歧义。这意味着会先计算 and 表达式,其结果再用于 or 表达式中。
因此,会先计算表达式 item["Quantity"] > 2 and item["Success"]。只有包含数据线的那笔交易会得到 truthy;其余条目评估为 falsy。
随后将该 and 表达式的值与 or 运算符一起使用。or 表达式对任何对 and 表达式为 truthy 的条目(这里只是数据线那笔)以及价格超过 100 美元的条目返回 truthy。超过阈值的有两笔:咖啡机和耳机。
Python:括号与逻辑运算符
不过,如果我们的需求是:价格超过 100 美元或数量超过 2,但还要确保交易成功,该怎么办?此时我们希望先评估 or 表达式,使其优先级高于 and。可以通过给 or 表达式加上括号来实现:
for item in data :
if ( item[ "Price" ] > 100 or item[ "Quantity" ] > 2 ) and item[ "Success" ] :
print ( item)
技术支持
{ 'Item' : 'Headphones' , 'Price' : 250 , 'Quantity' : 1 , 'Success' : True}
{ 'Item' : 'Cables' , 'Price' : 15.99 , 'Quantity' : 3 , 'Success' : True}
技术支持
额外的括号让 or 表达式获得优先级。咖啡机交易不再被包含,因为它在第二个 and 操作数上评估为 falsy。
Python:not 的优先级高于 and 与 or
not 的优先级高于 and 和 or。因此会先于另外两个逻辑运算符进行求值。
来看下面这个同时包含 not 和 and 的 if 语句:
for item in data :
if not item[ "Success" ] and item[ "Price" ] > 100 :
print ( item)
技术支持
{ 'Item' : 'Coffee Machine' , 'Price' : 125 , 'Quantity' : 1 , 'Success' : False}
技术支持
由于 not 会先被求值,这个表达式会先将 not 应用于 item["Success"]。随后,not 表达式的结果作为 and 表达式的第一个操作数。只有咖啡机这一条满足条件——它是唯一失败且价格超过 100 美元的交易。
不过,我们可以用括号让 and 拥有更高优先级:
for item in data :
if not ( item[ "Success" ] and item[ "Price" ] > 100 ) :
print ( item)
技术支持
{ 'Item' : 'Python Book' , 'Price' : 50 , 'Quantity' : 1 , 'Success' : True}
{ 'Item' : 'Coffee Machine' , 'Price' : 125 , 'Quantity' : 1 , 'Success' : False}
{ 'Item' : 'Cables' , 'Price' : 15.99 , 'Quantity' : 3 , 'Success' : True}
技术支持
在这种情况下,会先评估 and 表达式。只有耳机这一条为 True,因为它是唯一价格超过 100 美元且交易成功的条目。不过我们在括号表达式前加了 not,因此代码会输出剩余三条交易。
一般来说,如果一个表达式因为包含太多运算符而变得过于复杂,最好将其拆分以提高可读性。
结论
Python 的逻辑运算符 and、or 和 not 在广泛的编程与数据科学应用中被大量使用。它们复现了逻辑与数学中广泛使用的布尔逻辑运算 AND、OR 和 NOT 的行为。
不过,Python 的这些运算符可以接受任意对象,而不仅是布尔值。and 与 or 使用短路求值,并返回某个操作数作为输出。
Python 的逻辑运算符是过滤数据、识别数据集特征以及创建控制程序流程的复杂规则的关键工具。如果您想进一步学习,欢迎查看这条包含九门课程的 Data Analyst With Python 职业路径。
在编程中,我们经常需要基于多个条件来做决策。例如,只有当若干条件同时满足时,我们才执行某个操作。或者,当若干条件中任意一个满足时,我们触发另一种操作。
为处理这些场景,Python 提供了一组逻辑运算符 –
and、or、not。在本教程中,我们将学习 Python 逻辑运算符的工作原理,以及如何在编程和数据科学中使用它们。请注意,我们将用大写的 AND、OR 和 NOT 来抽象表示这些运算符;而提到具体的 Python 关键字时,使用
and、or和not这种写法。如果您在寻找系统化的 Python 课程路径,可以查看这条包含六门课程的 Python Programming 技能路径。
在深入细节之前,先给赶时间的您一个非常简短的答案。
简短回答:什么是 Python 逻辑运算符?
Python 的逻辑运算符(
and、or、not)是一些特殊关键字,它们在代码中起到连接词的作用,用于在单个表达式内连接并评估多个条件。看看这个示例:
这里,and 运算符确保仅当
两个条件都满足时才打印消息:气温高于 20 度且是晴天。再看一个使用
or运算符的示例:在这种情况下,只要要么是晴天,要么我们带了伞,我们就会出去散步。
最后,
not运算符会翻转条件的真值:这里,只有在不是晴天时才会打印消息。
逻辑运算符为我们提供了一种简洁而强大的方式来表达复杂条件,使程序能够基于多种因素做出决策。现在,让我们更深入地看看,先从
and逻辑运算符开始。Python:
and运算符在布尔逻辑中,AND 运算比较两个值或表达式。只有当两个值都为 true 时才产生 true 的结果。如果其中一个或两个值为 false,AND 运算的结果就是 false。下面是 AND 的行为总结:
运算
输出值
true AND true
true
true AND false
false
false AND true
false
false AND false
false
我们可以用 Python 的
and运算符重现这张真值表:options变量包含两个布尔值。嵌套的for循环两次遍历 options,以生成True和False的所有排列组合。常见情况下,作为 and 操作数的表达式会包含比较或相等运算符:
只有当名字少于五个字母且以
"J"开头时才会打印。两个条件都必须满足。比较和相等运算符(如
<和==)的结果为True或False。不过,Python 的
and运算符可作用于任意数据类型,而不只是布尔值True和False。其输出也可以是任意数据类型。本节我们将更详细地探究 Python 的
and运算符。首先讨论「真值性」。Python:truthy 与 falsy
每个 Python 对象都可以用内置的
bool()转换为布尔类型。如果bool(object)返回True,该对象为 truthy;如果返回False,则为 falsy。Python 的
and运算符会查看其操作数的真值性。如果两个操作数都为 truthy,and也会返回一个 truthy 值;如果有一个或两个为 falsy,and返回一个 falsy 值。看几个例子:再来看这个示例:
最后看这个示例:
数值类型(如整数、浮点数)在非零时为 truthy,等于零时为 falsy。序列类型(如字符串)在非空时为 truthy,空时为 falsy。
因此,上述三个示例中,只有第一个满足 and 运算符要求的「两个操作数都为 truthy」,从而评估为 truthy。
and运算符并不总是返回布尔值。包含and的表达式也可能直接评估为某个操作数。我们用刚才的示例更深入地看看。与其放在if里,不如直接求值:能看出这些表达式发生了什么吗?
先说第三个示例,两个操作数是
0和"python"。and需要两个 truthy 操作数。由于第一个是0,它是 falsy,因此无需检查第二个操作数,因为无论第二个值如何,整个表达式都将是 falsy。不过,
and运算符并不会返回False,而是直接返回第一个操作数。由于第一个操作数是 falsy,整个and表达式的真值性为 falsy。在 Python 中这不会有问题,因为在需要真或假值的上下文中,Python 会使用对象的真值性。在第一个示例中,第一个操作数
42为 truthy。程序会再评估第二个操作数并返回它。第二个操作数是字符串"python",它是 truthy,因此整个表达式评估为 truthy。在第二个示例中,第一个操作数同样是
42。由于它是 truthy,程序会评估并返回第二个操作数,即空字符串。空字符串为 falsy,因此整个and表达式评估为 falsy。当第一个操作数为 truthy 时,
and运算符总是返回第二个操作数的值,不管第二个操作数是 truthy 还是 falsy。当第一个操作数为 falsy 时,Python 不会再评估第二个操作数。这称为短路,是一种惰性求值。您可以用下面的代码验证:
第二个操作数是
5/0,通常会抛出ZeroDivisionError。但在这个示例中,由于第一个操作数是 falsy,表达式5/0不会被求值,因此不会抛出异常。示例:程序员的网上商店
接下来看一个贴近实际应用的简单示例。为程序员提供商品的网店,其交易通过 API 记录并访问。数据被转换为字典构成的列表。列表中的每个元素代表一条交易记录,每条交易都是一个包含相关信息的字典:
每笔交易都包含商品名称与价格、订单数量,以及交易是否成功。
假设我们需要价格不低于 100 美元且交易成功的记录。可以使用
and运算符来筛选所需行:输出显示只有一条交易同时满足两个条件。对于交易列表中的每个条目,
if语句会检查两个表达式的真值性:"Success"对应的值要么是True,要么是False。item["Price"] >= 100中的「大于等于」运算也返回True或False。Python 书和数据线不满足价格要求(均低于 100 美元)。咖啡机价格超过该阈值,但交易未成功,因此未被打印。
稍后我们会回到这个网店示例。
下一节将关注
or运算符。Python:
or运算符在布尔逻辑中,OR 逻辑运算符需要两个操作数。只要至少一个操作数为 true,其结果就为 true:
运算
输出值
true OR true
true
true OR false
true
false OR true
true
false OR false
false
我们可以用 Python 的
or运算符重现这张真值表:我们也可以回到之前的人名示例,但把
and换成or:现在
if语句包含一个or表达式。因此,for循环会打印所有要么少于五个字母,要么以字母"J"开头的名字。字符串"Jane"同时满足两个条件;其他被打印的名字满足其中一个条件。Python
or运算符:truthy 与 falsyor运算符同样基于 truthy 和 falsy 值,而不仅仅是布尔值True与False。来看一些示例:再看这个示例:
最后再看这个示例:
在第一个示例中,整数
42和非空列表[10, 20, 30]都是 truthy。由于or只需至少一个操作数为 truthy,整个表达式评估为 truthy。在第二个示例中,
42是 truthy,而空列表[]是 falsy(因为它是空序列)。两个操作数中至少有一个为 truthy,因此整个 or 表达式评估为 truthy。在最后一个示例中,
0和[]都是 falsy,因此整个表达式评估为 falsy。or运算符在评估表达式时也会使用短路,以避免不必要的求值。下面的示例可以说明这一点:在第一个示例中,第一个操作数
42是 truthy。由于or只需要一个 truthy 操作数即可确定整个表达式的真值性,因此会立即返回第一个操作数。第二个操作数不会被求值,因为其值不影响最终结果。or返回的是第一个操作数42,而不是布尔值True。在 Python 中,在if和 while 等语境下,任何 truthy 值都与布尔值True具有相同效果。在第二个示例中,第一个操作数同样是
42,即便第二个操作数是 falsy,表达式仍返回该整数。在第三和第四个示例中,第一个操作数是空列表(falsy),因此都会返回第二个操作数。
示例:程序员的网上商店
让我们回到向程序员销售商品的网店交易记录。以下是本例使用的四笔示例交易:
您需要挑出一些交易,以便进一步研究客户行为。您想找出那些交易失败的,或包含价格低于 75 美元商品的交易。由于有两个条件且只需要满足其一,您可以使用
or运算符:这个
for循环会显示满足至少一个条件的行。Python 书和数据线因价格低于 75 美元而被包含;咖啡机因交易未成功而被包含。对于筛选未成功的交易,还有另一种方式,下一节我们将探讨。
Python:
not运算符NOT 运算符不同于 AND 和 OR,它只需要一个操作数。NOT 会把 true 变为 false,反之亦然。下面是 NOT 的真值表:
运算
输出值
NOT true
false
NOT false
true
我们可以用 Python 的
not运算符来复现:Python
not运算符:truthy 与 falsy与
and和or一样,not的操作数也不必是布尔值。由于任意对象要么为 truthy,要么为 falsy,因此任意对象都可以与not一起使用。再看这个示例:
使用
not时,truthy 值会被转换为False,falsy 值会被转换为True。与
and和or不同,not运算符总是返回一个布尔对象:示例:程序员的网上商店
在前面的部分,我们使用了网店的交易记录。在这个示例中,我们想要显示所有未成功的交易。一种做法是使用相等运算符
==检查data["Success"]是否等于False。不过,我们也可以使用not运算符:由于未成功交易的
item["Success"]等于False,因此not item["Success"]返回True。于是 for 循环会打印未成功的交易:下一节我们将学习如何在一个表达式中组合多个逻辑运算符。
Python:运算符优先级
到目前为止的示例中,每次只使用了一个逻辑运算符。本节将看看在单个表达式中组合多个逻辑运算符时会发生什么。
Python:
and的优先级高于or我们继续使用之前的网店交易。来试试下面的条件语句:
if语句包含两个逻辑运算符。在研究 Python 如何处理这个表达式之前,我们先把它翻译成一句英文描述:如果商品价格超过 100 美元,或者售出数量大于 2 且交易成功,则打印该条目。如果不加更多标点,这句话是有歧义的;即便加了更多逗号,也可能让人困惑。比如,是否应包含咖啡机的那笔交易?它的价格超过阈值,但交易并不成功。
Python 通过赋予
and高于or的优先级来消除这种歧义。这意味着会先计算and表达式,其结果再用于or表达式中。因此,会先计算表达式
item["Quantity"] > 2 and item["Success"]。只有包含数据线的那笔交易会得到 truthy;其余条目评估为 falsy。随后将该 and 表达式的值与
or运算符一起使用。or表达式对任何对 and 表达式为 truthy 的条目(这里只是数据线那笔)以及价格超过 100 美元的条目返回 truthy。超过阈值的有两笔:咖啡机和耳机。Python:括号与逻辑运算符
不过,如果我们的需求是:价格超过 100 美元或数量超过 2,但还要确保交易成功,该怎么办?此时我们希望先评估
or表达式,使其优先级高于and。可以通过给or表达式加上括号来实现:额外的括号让
or表达式获得优先级。咖啡机交易不再被包含,因为它在第二个and操作数上评估为 falsy。Python:
not的优先级高于and与ornot的优先级高于and和or。因此会先于另外两个逻辑运算符进行求值。来看下面这个同时包含
not和and的 if 语句:由于
not会先被求值,这个表达式会先将not应用于item["Success"]。随后,not表达式的结果作为 and 表达式的第一个操作数。只有咖啡机这一条满足条件——它是唯一失败且价格超过 100 美元的交易。不过,我们可以用括号让
and拥有更高优先级:在这种情况下,会先评估
and表达式。只有耳机这一条为True,因为它是唯一价格超过 100 美元且交易成功的条目。不过我们在括号表达式前加了not,因此代码会输出剩余三条交易。一般来说,如果一个表达式因为包含太多运算符而变得过于复杂,最好将其拆分以提高可读性。
结论
Python 的逻辑运算符
and、or和not在广泛的编程与数据科学应用中被大量使用。它们复现了逻辑与数学中广泛使用的布尔逻辑运算 AND、OR 和 NOT 的行为。不过,Python 的这些运算符可以接受任意对象,而不仅是布尔值。
and与or使用短路求值,并返回某个操作数作为输出。Python 的逻辑运算符是过滤数据、识别数据集特征以及创建控制程序流程的复杂规则的关键工具。如果您想进一步学习,欢迎查看这条包含九门课程的 Data Analyst With Python 职业路径。