9 回答 9
This answer is useful
117
我相信 Python 对关系运算符序列具有特殊情况处理,以使范围比较易于表达。能说0 < x <= 5比说要好得多(0 < x) and (x <= 5)。
这些称为链式比较。这是他们文档的链接。
对于您谈论的其他情况,括号强制一个关系运算符在另一个之前应用,因此它们不再是链式比较。由于True和False具有整数值,因此您可以从带括号的版本中得到答案。
于 2011-05-20T15:25:47.643 回答
This answer is useful
42
因为
(0 < 0) and (0 == 0)
是False。您可以将比较运算符链接在一起,它们会自动扩展为成对比较。
编辑——澄清 Python 中的 True 和 False
在 Python中True和False只是 的实例bool,它是 的子类int。换句话说,True真的只是1。
关键是您可以像使用整数一样使用布尔比较的结果。这会导致令人困惑的事情,例如
>>> (1==1)+(1==1)
2
>>> (2<1)<1
True
但是,只有当您将比较括起来以便首先评估它们时,这些才会发生。否则 Python 将扩展比较运算符。
于 2011-05-20T15:28:58.337 回答
This answer is useful
18
您遇到的奇怪行为来自蟒蛇连锁条件的能力。由于它发现 0 不小于 0,因此它决定整个表达式的计算结果为 false。一旦你把它分解成单独的条件,你就改变了功能。它最初基本上是a < b && b == c针对您的原始声明进行测试a < b == c。
另一个例子:
>>> 1 < 5 < 3
False
>>> (1 < 5) < 3
True
于 2011-05-20T15:27:43.317 回答
This answer is useful
9
>>> 0 < 0 == 0
False
这是一个链式比较。如果每个成对比较依次为真,则返回真。它相当于(0 < 0) and (0 == 0)
>>> (0) < (0 == 0)
True
这相当于0 < Truewhich 的计算结果为 True。
>>> (0 < 0) == 0
True
这相当于False == 0which 的计算结果为 True。
>>> 0 < (0 == 0)
True
等效于0 < Truewhich,如上所述,评估为 True。
于 2011-05-20T15:37:12.670 回答
This answer is useful
8
查看反汇编(字节代码)很明显为什么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
注意第 0-8 行:这些行检查是否0 < 0明显返回False到 python 堆栈。
现在注意第 11 行:JUMP_IF_FALSE_OR_POP 23
这意味着如果0 < 0返回False执行跳转到第 23 行。
现在,0 < 0is False,因此进行了跳转,这使堆栈留下了 a False,它是整个 expression 的返回值0 < 0 == 0,即使该== 0部分甚至没有被检查。
所以,总而言之,答案就像这个问题的其他答案一样。
0 < 0 == 0有特殊的意义。编译器将此评估为两个术语:0 < 0和0 == 0. 与and它们之间的任何复杂布尔表达式一样,如果第一个失败,则甚至不检查第二个。
希望这对事情有所启发,我真的希望我用来分析这种意外行为的方法能鼓励其他人在未来尝试同样的方法。
于 2013-05-26T19:18:26.510 回答
This answer is useful
2
也许文档中的这段摘录可以提供帮助:
这些就是所谓的“富比较”方法,在__cmp__()下面优先使用比较运算符。运算符符号和方法名的对应关系如下:x x.__lt__(y)、x<=y调用x.__le__(y)、 x==y调用和 调用x.__eq__(y)、调用 、调用 。x!=yx<>yx.__ne__(y)x>yx.__gt__(y)x>=yx.__ge__(y) 如果富比较方法NotImplemented没有为给定的一对参数实现操作,则它可能会返回单例。按照惯例,False返回True成功比较。但是,这些方法可以返回任何值,因此如果在布尔上下文中使用比较运算符(例如,在 if 语句的条件中),Python 将调用bool()该值来确定结果是真还是假。 比较运算符之间没有隐含的关系。的真理x==y并不意味着它x!=y 是错误的。因此,在定义 时 __eq__(),还应该定义__ne__()操作符的行为与预期一致。__hash__()有关创建支持自定义比较操作且可用作字典键的可散列对象的一些重要说明,请参阅上的段落。 这些方法没有交换参数版本(当左参数不支持操作但右参数支持时使用);更确切地说,__lt__()和__gt__() 是彼此的反映,__le__() 并且__ge__()是彼此的反映,__eq__()并且__ne__() 是自己的反映。 对丰富的比较方法的论证从不强制。 这些是比较,但由于您正在链接比较,您应该知道: 比较可以任意链接,例如,x < y <= z等价于x < y and y <= z,除了 y 只被评估一次(但在这两种情况下,当 x < y 被发现为假时,z 根本不被评估)。 形式上,如果 a, b, c, ..., y, z 是表达式并且 op1, op2, ..., opN 是比较运算符,则 a op1 b op2 c ... y opN z 等价于 a op1 b和 b op2 c 和 ... y opN z,除了每个表达式最多计算一次。 于 2011-05-20T15:34:23.843 回答 This answer is useful 2 正如其他人提到x comparison_operator y comparison_operator z的那样,语法糖是(x comparison_operator y) and (y comparison_operator z)因为 y 只被评估一次。 所以你的表达式0 < 0 == 0是真的(0 < 0) and (0 == 0),它的计算False and True结果是它False。 于 2011-05-20T15:38:36.090 回答 This answer is useful 1 它就在这里,尽显荣耀。 >>> class showme(object): ... def __init__(self, name, value): ... self.name, self.value = name, value ... def __repr__(self): ... return " ... 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( False >>> (showme(1,0) < showme(2,0)) == showme(3,0) cmp( cmp( True >>> showme(1,0) < (showme(2,0) == showme(3,0)) cmp( cmp( True >>> 于 2011-05-21T14:37:16.293 回答 This answer is useful 0 我在想 Python 在魔法之间做的很奇怪。与1 < 2 < 3手段 2 相同,介于 1 和 3 之间。 在这种情况下,我认为它正在做 [middle 0] 大于 [left 0] 并且等于 [right 0]。中 0 不大于左 0,因此它的计算结果为假。 于 2011-05-20T15:30:39.807 回答