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

为什么表达式0<;0==0在Python中返回False?,python,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 我相信Pytho

查看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

我相信Python对关系运算符序列有特殊的大小写处理,使范围比较易于表达。能说
0a
的原始语句
a

另一个例子:

>>> 1 < 5 < 3
False

>>> (1 < 5) < 3
True
>>1<5<3
假的
>>> (1 < 5) < 3
真的
因为

(0 < 0) and (0 == 0)

但是,只有在将比较插入括号以便首先对其进行评估时,才会发生这些情况。否则Python将扩展比较运算符。

我认为Python正在这样做,这在魔法之间很奇怪。与
1<2<3
相同,表示2介于1和3之间


在这种情况下,我认为它所做的[middle 0]大于[left 0],等于[right 0]。中间的0不大于左边的0,因此其计算结果为false。

这段摘录可能有帮助:

这些就是所谓的“富人” “比较”方法,并调用 对于首选的比较运算符 到下面的
\uu cmp\uu()
。通信 运算符符号与方法之间的关系 名称如下:
x=y
调用
x.\uu_u_u(y)

丰富的比较方法可能会返回 单例
未实现
,如果 不执行针对的操作 给定两个参数。通过 常规,
False
True
是 返回以进行成功比较。 但是,这些方法可以返回任何 值,因此如果比较运算符 在布尔上下文中使用(例如,在 if语句的条件), Python将对值调用
bool()
确定结果是否为真 错

没有隐含的关系 在比较运算符中。这个
x==y的真理并不意味着
x=y
这是错误的。因此,在定义
\uuuu eq\uuuu()
,还应定义
\uuuu ne\uuuuuu()
,以便运算符按预期运行。见该段 在
\uuuu hash\uuuu()
上查看一些重要注释 关于创建哈希对象 支持自定义比较操作 并可用作字典键

没有交换的参数版本 这些方法中的一种(当 left参数不支持 操作,但参数正确 是的);相反,
\uu lt\uu()
\uu gt\uu()
是彼此的反映,
\uuuuu le\uuuuuu()
\uuu ge\uuu()
是彼此的 反射和
\uuuu eq\uuuu()
\uuu ne\uuuuu()
都是他们自己的反映

丰富比较方法的参数 他们从不被强迫

这些都是比较,但既然你是,你应该知道:

比较可以链接起来 任意,例如,
x等价于
0
,如上所述,其计算结果为True。

正如其他人所提到的
x比较算子y比较算子z
(x比较算子y)和(y比较算子z)
的语法糖,加上y只计算一次

>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True

因此,你的表达式
0<0==0
实际上是
(0<0)和(0==0)
,它的计算结果是
False和
True,这就是
False

,这是它的荣耀所在

>>> class showme(object):
...   def __init__(self, name, value):
...     self.name, self.value = name, value
...   def __repr__(self):
...     return "<showme %s:%s>" % (self.name, self.value)
...   def __cmp__(self, other):
...     print "cmp(%r, %r)" % (self, other)
...     if type(other) == showme:
...       return cmp(self.value, other.value)
...     else:
...       return cmp(self.value, other)
... 
>>> showme(1,0) < showme(2,0) == showme(3,0)
cmp(<showme 1:0>, <showme 2:0>)
False
>>> (showme(1,0) < showme(2,0)) == showme(3,0)
cmp(<showme 1:0>, <showme 2:0>)
cmp(<showme 3:0>, False)
True
>>> showme(1,0) < (showme(2,0) == showme(3,0))
cmp(<showme 2:0>, <showme 3:0>)
cmp(<showme 1:0>, True)
True
>>> 
>>类showme(对象):
...   定义初始化(自身、名称、值):
...     self.name,self.value=名称,值
...   定义报告(自我):
...     返回“”%(self.name,self.value)
...   定义cmp(自身、其他):
...     打印“cmp(%r,%r)”%(自身,其他)
...     如果类型(其他)==showme:
...       返回cmp(self.value,other.value)
...     其他:
...       返回cmp(自我值,其他)
... 
>>>showme(1,0)>>(showme(1,0)>>showme(1,0)<(showme(2,0)=showme(3,0))
cmp(,)
cmp(,真)
真的
>>> 

查看反汇编(字节代码),很明显为什么
0<0==0
False

下面是对该表达式的分析:

>>>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
导入dis >>>def(): ... 0 < 0 == 0 >>>dis.dis(f) 2 0负载常数1(0) 3负载常数1(0) 6双上 七点三分 8比较操作0(>23旋转两次 24件流行上衣 >>25件流行上衣 26负载常数0(无) 29返回值
注意第0-8行:这些行检查
0<0
,这显然会在python堆栈上返回
False

现在注意第11行:
IF\u FALSE\u或\u POP 23跳转
这意味着如果
0<0
返回
False
执行跳转到第23行

现在,
0<0
False
,因此进行跳转,跳转将在堆栈中留下一个
False
,这是整个表达式
0<0==0
的返回值,即使
==0
部分甚至没有被检查

因此,总而言之,答案就像这个问题的其他答案一样。
0<0==0
有一个特殊的含义。编译器将其计算为两个术语:
0<0
0==0
。与任何介于两者之间的复杂布尔表达式一样,如果第一个表达式失败,则第二个表达式甚至不会被检查

希望这能让事情有所启发,我也希望我用来分析这种意外行为的方法能鼓励其他人在将来也尝试同样的方法。

OMG,
a>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True
>>> class showme(object):
...   def __init__(self, name, value):
...     self.name, self.value = name, value
...   def __repr__(self):
...     return "<showme %s:%s>" % (self.name, self.value)
...   def __cmp__(self, other):
...     print "cmp(%r, %r)" % (self, other)
...     if type(other) == showme:
...       return cmp(self.value, other.value)
...     else:
...       return cmp(self.value, other)
... 
>>> showme(1,0) < showme(2,0) == showme(3,0)
cmp(<showme 1:0>, <showme 2:0>)
False
>>> (showme(1,0) < showme(2,0)) == showme(3,0)
cmp(<showme 1:0>, <showme 2:0>)
cmp(<showme 3:0>, False)
True
>>> showme(1,0) < (showme(2,0) == showme(3,0))
cmp(<showme 2:0>, <showme 3:0>)
cmp(<showme 1:0>, True)
True
>>> 
>>>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