【发布时间】:2010-07-05 20:09:30
【问题描述】:
如果你在 python 中写类似的东西
foo==bar and spam or eggs
如果布尔语句为真,python 似乎返回垃圾邮件,否则返回鸡蛋。有人可以解释这种行为吗?为什么表达式不像一个长布尔值那样被评估?
编辑:具体来说,我试图弄清楚为什么“垃圾邮件”或“鸡蛋”作为表达式的结果返回的机制。
【问题讨论】:
标签: python syntax boolean-expression
如果你在 python 中写类似的东西
foo==bar and spam or eggs
如果布尔语句为真,python 似乎返回垃圾邮件,否则返回鸡蛋。有人可以解释这种行为吗?为什么表达式不像一个长布尔值那样被评估?
编辑:具体来说,我试图弄清楚为什么“垃圾邮件”或“鸡蛋”作为表达式的结果返回的机制。
【问题讨论】:
标签: python syntax boolean-expression
运算符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 是指在布尔上下文中评估为 false 或 true 的值。
然而,这个和/或成语在没有更好的选择的时代很有用,但现在有更好的方法:
spam if foo==bar else eggs
and/or 成语的问题(除了让初学者感到困惑之外)是,如果条件为真但垃圾邮件的评估结果为假值(例如空字符串),它会给出错误的结果。因此,您应该避免它。
【讨论】:
else 而不是 or。现已修复。
code = True if '```' in line and not code else False
这就是 Python 布尔运算符的工作方式。
来自the documentation(最后一段解释了为什么操作员按照他们的方式工作是个好主意):
在布尔运算的上下文中, 以及当表达式被使用时 控制流语句,如下 值被解释为假:
False,None, 数字零 类型和空字符串和 容器(包括字符串、元组、 列表、字典、集合和 冻结集)。所有其他值是 解释为真。 (见__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'产生False,而不是''。)
【讨论】:
原因是 Python 使用所涉及变量的实际值来评估布尔表达式,而不是将它们限制为 True 和 False 值。以下值被认为是错误的:
NoneFalse''、()、[]、{})__nonzero__() 或__len__() 方法返回0 或False 的用户定义类型
有关详细信息,请参阅 Python 文档的 Truth Value Testing 部分。特别是:
除非另有说明,否则具有布尔结果的操作和内置函数始终返回
0或False为假,1或True为真。 (重要的例外:布尔运算or和and总是返回它们的操作数之一。)
【讨论】:
尝试使用括号使表达式明确。就这样,你得到:
(foo == bar and spam) or eggs
【讨论】: