跳至主要内容

Python 逻辑运算符:上手入门

Python 提供三个逻辑运算符:and、or 和 not。它们也称为布尔运算符,用于评估多个条件并确定表达式的整体真值。
· 13分钟 阅读

使用 AI 探索

在编程中,我们经常需要基于多个条件来做决策。例如,只有当若干条件同时满足时,我们才执行某个操作。或者,当若干条件中任意一个满足时,我们触发另一种操作。

为处理这些场景,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 职业路径。

Stephen Gruppetta

作者

Stephen Gruppetta

我在马耳他大学完成了本科阶段的物理与数学学习。随后前往伦敦,并在帝国理工学院取得物理学博士学位,研究用于成像人类视网膜的新型光学技术。现在,我专注于撰写与传播 Python 相关内容,并教授 Python。

Python 逻辑运算符常见问题

我可以用 and 运算符一次测试多个条件吗?

可以,您可以使用 and 运算符将多个条件串联在一起。例如:if x > 5 and x < 10 and x != 7。

and 运算符与按位与运算符(&)有什么区别?

and 运算符对布尔值执行逻辑与运算,只有当两个操作数都为 True 时才返回 True。按位与运算符(&)则对整数值的二进制表示执行按位与运算。

Python 是否像某些其他语言那样具有 && 和 || 运算符?

不会。Python 使用关键字 and 和 or 来进行逻辑运算,而不是使用符号 && 和 ||。

主题