4.6. andor 的特殊性质

Python 中,andor 按照预期执行布尔逻辑,但它们不返回布尔值;相反,它们返回正在比较的实际值之一。

示例 4.15. 介绍 and

>>> 'a' and 'b'         1
'b'
>>> '' and 'b'          2
''
>>> 'a' and 'b' and 'c' 3
'c'
1 使用 and 时,将从左到右在布尔上下文中评估值。0''[](){}None 在布尔上下文中为假;其他所有内容均为真。好吧,几乎所有内容。默认情况下,类的实例在布尔上下文中为真,但您可以在类中定义特殊方法以使实例评估为假。您将在第 5 章中学习有关类和特殊方法的所有内容。如果所有值在布尔上下文中均为真,则 and 返回最后一个值。在这种情况下,and 评估 'a'(为真),然后评估 'b'(为真),并返回 'b'
2 如果任何值在布尔上下文中为假,则 and 返回第一个假值。在这种情况下,'' 是第一个假值。
3 所有值均为真,因此 and 返回最后一个值 'c'

示例 4.16. 介绍 or

>>> 'a' or 'b'          1
'a'
>>> '' or 'b'           2
'b'
>>> '' or [] or {}      3
{}
>>> def sidefx():
...     print "in sidefx()"
...     return 1
>>> 'a' or sidefx()     4
'a'
1 使用 or 时,将像 and 一样从左到右在布尔上下文中评估值。如果有任何值为真,则 or 立即返回该值。在这种情况下,'a' 是第一个真值。
2 or 评估 ''(为假),然后评估 'b'(为真),并返回 'b'
3 如果所有值均为假,则 or 返回最后一个值。or 评估 ''(为假),然后评估 [](为假),然后评估 {}(为假),并返回 {}
4 请注意,or 仅评估值,直到找到在布尔上下文中为真的值,然后忽略其余值。如果某些值可能具有副作用,则此区别很重要。在这里,永远不会调用函数 sidefx,因为 or 评估 'a'(为真),并立即返回 'a'

如果您是 C 黑客,您当然熟悉 bool ? a : b 表达式,如果 bool 为真,则该表达式求值为 a,否则求值为 b。由于 andorPython 中的工作方式,您可以完成相同的事情。

4.6.1. 使用 and-or 技巧

示例 4.17. 介绍 and-or 技巧

>>> a = "first"
>>> b = "second"
>>> 1 and a or b 1
'first'
>>> 0 and a or b 2
'second'
1 此语法看起来类似于 C 中的 bool ? a : b 表达式。整个表达式从左到右求值,因此首先求值 and1 and 'first' 求值为 'first',然后 'first' or 'second' 求值为 'first'
2 0 and 'first' 求值为 False,然后 0 or 'second' 求值为 'second'

但是,由于此 Python 表达式只是布尔逻辑,而不是该语言的特殊构造,因此 Python 中的此 and-or 技巧与 C 中的 bool ? a : b 语法之间存在一个极其重要的区别。如果 a 的值为假,则该表达式的行为将与您的预期不符。(您能告诉我我被这个咬过吗?不止一次?)

示例 4.18. and-or 技巧失败的情况

>>> a = ""
>>> b = "second"
>>> 1 and a or b         1
'second'
1 由于 a 是一个空字符串,Python 在布尔上下文中将其视为假,因此 1 and '' 求值为 '',然后 '' or 'second' 求值为 'second'。糟糕!这不是您想要的。

a 在布尔上下文中为假时,and-or 技巧(bool and a or b)的行为将与 C 表达式 bool ? a : b 不同。

因此,and-or 技巧的真正技巧是确保 a 的值永远不会为假。一种常见的方法是将 a 转换为 [a] 并将 b 转换为 [b], 然后获取返回列表的第一个元素,该元素将是 ab

示例 4.19. 安全地使用 and-or 技巧

>>> a = ""
>>> b = "second"
>>> (1 and [a] or [b])[0] 1
''
1 由于 [a] 是一个非空列表,因此它永远不会为假。即使 a0'' 或其他一些假值,列表 [a] 也为真,因为它有一个元素。

到目前为止,此技巧似乎弊大于利。毕竟,您可以使用 if 语句完成相同的事情,那么为什么要费心呢?好吧,在许多情况下,您是在两个常量值之间进行选择,因此您可以使用更简单的语法而不必担心,因为您知道 a 值将始终为真。即使您需要使用更复杂的更安全的表单,也有充分的理由这样做。例如,在 Python 中,某些情况下不允许使用 if 语句,例如在 lambda 函数中。

有关 and-or 技巧的更多阅读材料