在 python 中,如果你写类似的东西
foo==bar and spam or eggs
如果布尔语句为真,python 似乎返回垃圾邮件,否则返回鸡蛋。有人可以解释这种行为吗?为什么表达式不像一个长布尔值那样被评估?
编辑:具体来说,我试图弄清楚为什么“垃圾邮件”或“鸡蛋”作为表达式的结果被返回的机制。
在 python 中,如果你写类似的东西
foo==bar and spam or eggs
如果布尔语句为真,python 似乎返回垃圾邮件,否则返回鸡蛋。有人可以解释这种行为吗?为什么表达式不像一个长布尔值那样被评估?
编辑:具体来说,我试图弄清楚为什么“垃圾邮件”或“鸡蛋”作为表达式的结果被返回的机制。
运算符and
和or
是短路的,这意味着如果表达式的结果可以从仅计算第一个操作数推导出来,则不计算第二个操作数。例如,如果您有表达式a or b
并且a
计算结果为 true,那么不管是什么b
,表达式的结果都是 true,因此b
不会被计算。它们实际上的工作方式如下:
a and b
: 如果 a 为假,则不计算 b 并返回 a,否则返回 b。a or b
: 如果 a 为真,则不计算 b 并返回 a,否则返回 b。Falsey 和truthy 是指在布尔上下文中评估为假或真的值。
然而,这个和/或成语在没有更好的选择的日子里很有用,但现在有更好的方法:
spam if foo==bar else eggs
和/或成语的问题(除了让初学者感到困惑之外)是如果条件为真但垃圾邮件评估为假值(例如空字符串),它会给出错误的结果。出于这个原因,你应该避免它。
这就是 Python 布尔运算符的工作方式。
从文档中(最后一段解释了为什么操作员按照他们的方式工作是个好主意):
在布尔运算的上下文中,以及当控制流语句使用表达式时,以下值被解释为 false:
False
,None
, 所有类型的数字零,以及空字符串和容器(包括字符串、元组、列表、字典、集合和冻结集)。所有其他值都被解释为 true。(有关__nonzero__()
更改此设置的方法,请参见特殊方法。)如果其参数为假,则运算符
not
产生,否则。True
False
表达式
x and y
首先计算x
; 如果x
为假,则返回其值;否则,y
评估并返回结果值。表达式
x or y
首先计算x
; 如果x
为真,则返回其值;否则,评估 y 并返回结果值。(注意,既不限制
and
也不or
限制它们返回的值和类型False
,True
而是返回最后评估的参数。这有时很有用,例如,如果s
是一个字符串,如果它是空的,则应该用默认值替换,表达式s or 'foo'
产生期望的值。因为not
无论如何都必须创造一个值,所以它不会费心返回与其参数相同类型的值,例如,not 'foo'
yieldFalse
,而不是''
。)
原因是 Python 使用所涉及变量的实际值来评估布尔表达式,而不是将它们限制为True
和False
值。以下值被认为是错误的:
None
False
''
, ()
, []
, {}
)__nonzero__()
或方法的用户定义类型__len__()
False
有关更多信息,请参阅 Python 文档的真值测试部分。尤其:
除非另有说明,否则具有布尔结果的操作和内置函数始终返回
0
或False
为假和1
或为真。True
(重要的例外:布尔运算总是返回它们or
的and
操作数之一。)
尝试使用括号使表达式明确。就这样,你得到:
(foo == bar and spam) or eggs