【问题标题】:Python boolean expression and orPython 布尔表达式和或
【发布时间】:2010-07-05 20:09:30
【问题描述】:

如果你在 python 中写类似的东西

foo==bar and spam or eggs

如果布尔语句为真,python 似乎返回垃圾邮件,否则返回鸡蛋。有人可以解释这种行为吗?为什么表达式不像一个长布尔值那样被评估?

编辑:具体来说,我试图弄清楚为什么“垃圾邮件”或“鸡蛋”作为表达式的结果返回的机制。

【问题讨论】:

    标签: python syntax boolean-expression


    【解决方案1】:

    运算符andor 是短路的,这意味着如果表达式的结果可以从仅计算第一个操作数推导出来,则不计算第二个操作数。例如,如果您的表达式 a or ba 的计算结果为 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 成语的问题(除了让初学者感到困惑之外)是,如果条件为真但垃圾邮件的评估结果为假值(例如空字符串),它会给出错误的结果。因此,您应该避免它。

    【讨论】:

    • 'spam if foo==bar or eggs' 在 python 2.6.5 中显示语法错误,但 'spam if foo==bar else eggs' 可以正常工作。
    • @Zxaos:很抱歉。它应该是 else 而不是 or。现已修复。
    • 在“错误的结果......如果 foo 评估为虚假值”是指“垃圾邮件评估为虚假值”吗?
    • 所以这不起作用,连接条件:code = True if '```' in line and not code else False
    【解决方案2】:

    这就是 Python 布尔运算符的工作方式。

    来自the documentation(最后一段解释了为什么操作员按照他们的方式工作是个好主意):

    在布尔运算的上下文中, 以及当表达式被使用时 控制流语句,如下 值被解释为假: False, None, 数字零 类型和空字符串和 容器(包括字符串、元组、 列表、字典、集合和 冻结集)。所有其他值是 解释为真。 (见 __nonzero__() 一种改变这种情况的特殊方法。)

    运算符not 产生True,如果它 参数为假,False 否则。

    表达式 x and y 首先计算 x;如果x 为假,则其值为 回来;否则,评估 y 并返回结果值。

    表达式 x or y 首先计算 x;如果x 为真,则其值为 回来;否则,评估 y 并返回结果值。

    (请注意,andor 均不限制 他们返回的值和类型 FalseTrue,而是返回 最后评估的参数。这是 有时有用,例如,如果 s 是 应该被替换的字符串 默认值,如果为空,则 表达式s or 'foo' 产生 期望值。因为not 必须 无论如何发明一个值,它不会 费心返回相同的值 类型作为它的参数,例如,not 'foo' 产生 False,而不是 ''。)

    【讨论】:

      【解决方案3】:

      原因是 Python 使用所涉及变量的实际值来评估布尔表达式,而不是将它们限制为 TrueFalse 值。以下值被认为是错误的:

      • None
      • False
      • 任何数字类型的0
      • 空序列或集合(''()[]{}
      • 使用__nonzero__()__len__() 方法返回0 或False 的用户定义类型

      有关详细信息,请参阅 Python 文档的 Truth Value Testing 部分。特别是:

      除非另有说明,否则具有布尔结果的操作和内置函数始终返回 0False 为假,1True 为真。 (重要的例外:布尔运算 orand 总是返回它们的操作数之一。)

      【讨论】:

      • 好的,假设 foo 和 bar 相等。然后解释器应该评估 True 和垃圾邮件,这应该评估为 True,那么为什么会返回垃圾邮件呢?编辑:啊,好的。我从文档中看到。
      • @Zxaos:我已经用解释原因的文档中的引用更新了我的答案。
      【解决方案4】:

      尝试使用括号使表达式明确。就这样,你得到:

      (foo == bar and spam) or eggs
      

      【讨论】:

      • 我知道它被短路了,但我不确定为什么评估结果会返回垃圾邮件或鸡蛋。
      猜你喜欢
      • 1970-01-01
      • 2016-04-06
      • 2020-02-12
      • 1970-01-01
      • 2010-09-21
      • 2012-07-13
      • 2011-05-17
      • 2010-11-29
      • 2021-12-09
      相关资源
      最近更新 更多