为什么表达式0 <0 == 0在Python中返回False?

Mar*_*tos 133 python

在Python 2.6中查看Queue.py,我发现这个构造我发现有点奇怪:

def full(self):
    """Return True if the queue is full, False otherwise
    (not reliable!)."""
    self.mutex.acquire()
    n = 0 < self.maxsize == self._qsize()
    self.mutex.release()
    return n
Run Code Online (Sandbox Code Playgroud)

如果maxsize为0,则队列永远不会满.

我的问题是它如何适用于这种情况?如何0 < 0 == 0被认为是假的?

>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
Run Code Online (Sandbox Code Playgroud)

Omn*_*ous 110

我相信Python对关系运算符的序列有特殊的处理,使得范围比较易于表达.能够说出来0 < x <= 5比说出来要好得多(0 < x) and (x <= 5).

这些被称为链式比较.这是他们的文档链接.

在你谈到的其他情况下,括号强制一个关系运算符在另一个之前应用,因此它们不再是链式比较.并且由于True并且False将值作为整数,您可以从括号中获得答案.


Kat*_*iel 40

因为

(0 < 0) and (0 == 0)
Run Code Online (Sandbox Code Playgroud)

False.您可以将比较运算符链接在一起,它们会自动扩展到成对比较中.


编辑 - 澄清Python中的真与假

在Python TrueFalse仅仅的情况下bool,这是一个子类int.换句话说,True真的只是1.

这一点是你可以使用与整数完全相同的布尔比较结果.这会导致令人困惑的事情

>>> (1==1)+(1==1)
2
>>> (2<1)<1
True
Run Code Online (Sandbox Code Playgroud)

但这些只会在您对比较进行括号处理时才会发生,以便首先对它们进行评估.否则Python将扩展比较运算符.

  • 昨天我看到一个有趣的用途是将布尔值用作整数.表达式''success'如果result_code == 0 else'failure'`可以改写为`('error','success')[result_code == 0]`,在此之前我从未见过用于选择的布尔值列表/元组中的项目. (2认同)

Tyl*_*ler 18

你经历的奇怪行为来自蟒蛇连锁条件的能力.由于它发现0不小于0,因此它决定整个表达式的计算结果为false.一旦你将其分解为单独的条件,你就会改变功能.它最初基本上是测试a < b && b == c你的原始声明a < b == c.

另一个例子:

>>> 1 < 5 < 3
False

>>> (1 < 5) < 3
True
Run Code Online (Sandbox Code Playgroud)

  • OMG,`a &lt; b &amp;&amp; b == c` 和 `a &lt; b == c` OO 一样 (2认同)

Dav*_*nan 9

>>> 0 < 0 == 0
False
Run Code Online (Sandbox Code Playgroud)

这是一个链式比较.如果每个成对比较依次为真,则返回true.它相当于(0 < 0) and (0 == 0)

>>> (0) < (0 == 0)
True
Run Code Online (Sandbox Code Playgroud)

这相当于0 < True评估为True.

>>> (0 < 0) == 0
True
Run Code Online (Sandbox Code Playgroud)

这相当于False == 0评估为True.

>>> 0 < (0 == 0)
True
Run Code Online (Sandbox Code Playgroud)

相当于0 < True,如上所述,评估为True.


Sat*_*atA 7

望着拆卸(字节码),这是显而易见的,为什么0 < 0 == 0False.

以下是对此表达式的分析:

>>>import dis

>>>def f():
...    0 < 0 == 0

>>>dis.dis(f)
  2      0 LOAD_CONST               1 (0)
         3 LOAD_CONST               1 (0)
         6 DUP_TOP
         7 ROT_THREE
         8 COMPARE_OP               0 (<)
        11 JUMP_IF_FALSE_OR_POP    23
        14 LOAD_CONST               1 (0)
        17 COMPARE_OP               2 (==)
        20 JUMP_FORWARD             2 (to 25)
   >>   23 ROT_TWO
        24 POP_TOP
   >>   25 POP_TOP
        26 LOAD_CONST               0 (None)
        29 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

注意第0-8行:这些行检查0 < 0哪些显然返回False到python堆栈.

现在注意第11行:JUMP_IF_FALSE_OR_POP 23 这意味着如果0 < 0返回False执行跳转到第23行.

现在,0 < 0False,所以进行了跳转,这使得堆栈具有一个False整数表达式的返回值0 < 0 == 0,即使该== 0部分甚至没有被检查.

因此,总而言之,答案就像在这个问题的其他答案中所说的那样. 0 < 0 == 0有特殊意义.编译器将其评估为两个术语:0 < 00 == 0.与and它们之间的任何复杂布尔表达式一样,如果第一个失败,那么第二个也不会被检查.

希望这有点启发,我真的希望我用来分析这种意外行为的方法将鼓励其他人在将来尝试相同的方法.