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

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

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 "" % (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(, )

False

>>> (showme(1,0) < showme(2,0)) == showme(3,0)

cmp(, )

cmp(, False)

True

>>> showme(1,0) < (showme(2,0) == showme(3,0))

cmp(, )

cmp(, True)

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 回答

相关推荐

蜻蜓fm如何调频 蜻蜓fm调频方法【详解】
林黛玉得的“痨病”,到底是个啥?
嗨钱网嗨秒贷多久到账
《快手新手必看!如何在直播中轻松进行连麦》
硅电容器简介
365be体育app

硅电容器简介

📅 06-30 👁️ 9503
怎样更改导航端口
365be体育app

怎样更改导航端口

📅 06-28 👁️ 9329
怎样更改导航端口
365be体育app

怎样更改导航端口

📅 06-28 👁️ 9329
怎样看出教练喜欢你
在 iPhone 或 iPad 上创建或打开 ZIP 文件