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

内容 隐藏
问题:为什么表达式0 在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 如果maxsize为0,则队列永远不会满。 我的问题是在这种情况下如何运作?如何0 < 0 == 0被认为是错误的? >>> 0 < 0 == 0 False >>> (0) < (0 == 0) True >>> (0 < 0) == 0 True >>> 0 < (0 == 0) True 点击查看英文原文 Looking into Queue.py in Python 2.6, I found this construct that I found a bit strange: 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 If maxsize is 0 the queue is never full. My question is how does it work for this case? How 0 < 0 == 0 is considered False? >>> 0 < 0 == 0 False >>> (0) < (0 == 0) True >>> (0 < 0) == 0 True >>> 0 < (0 == 0) True 回答 0 我相信Python对关系运算符的序列有特殊的处理方式,以使范围比较易于表达。可以说更好0 < x <= 5比好得多(0 < x) and (x <= 5)。 这些称为链接比较。这是他们文档的链接。 在您谈论的其他情况下,括号会强制在一个关系运算符之前应用一个关系运算符,因此它们不再是链式比较。并且由于True和的False值都是整数,因此您可以从括号中得到答案。 点击查看英文原文 I believe Python has special case handling for sequences of relational operators to make range comparisons easy to express. It’s much nicer to be able to say 0 < x <= 5 than to say (0 < x) and (x <= 5). These are called chained comparisons. And that’s a link to the documentation for them. With the other cases you talk about, the parenthesis force one relational operator to be applied before the other, and so they are no longer chained comparisons. And since True and False have values as integers you get the answers you do out of the parenthesized versions. 回答 1 因为 (0 < 0) and (0 == 0) 是False。您可以将比较运算符链接在一起,它们会自动扩展为成对比较。 编辑-关于Python中正确与错误的说明 在Python中True,False仅仅是的实例bool,它是的子类int。换句话说,True确实只有1。 这样做的目的是,您可以像完全使用整数一样使用布尔比较的结果。这导致诸如 >>> (1==1)+(1==1) 2 >>> (2<1)<1 True 但是,只有在您对比较加括号以使它们首先被评估时,这些情况才会发生。否则,Python将扩展比较运算符。 点击查看英文原文 Because (0 < 0) and (0 == 0) is False. You can chain together comparison operators and they are automatically expanded out into the pairwise comparisons. EDIT — clarification about True and False in Python In Python True and False are just instances of bool, which is a subclass of int. In other words, True really is just 1. The point of this is that you can use the result of a boolean comparison exactly like an integer. This leads to confusing things like >>> (1==1)+(1==1) 2 >>> (2<1)<1 True But these will only happen if you parenthesise the comparisons so that they are evaluated first. Otherwise Python will expand out the comparison operators. 回答 2 您遇到的奇怪行为来自python链接条件的能力。由于发现0不小于0,因此它决定整个表达式的计算结果为false。一旦将其分解为单独的条件,就在更改功能。最初,它实际上是在测试a < b && b == c您对的原始声明a < b == c。 另一个例子: >>> 1 < 5 < 3 False >>> (1 < 5) < 3 True 点击查看英文原文 The strange behavior your experiencing comes from pythons ability to chain conditions. Since it finds 0 is not less than 0, it decides the entire expression evaluates to false. As soon as you break this apart into seperate conditions, you’re changing the functionality. It initially is essentially testing that a < b && b == c for your original statement of a < b == c. Another example: >>> 1 < 5 < 3 False >>> (1 < 5) < 3 True 回答 3 >>> 0 < 0 == 0 False 这是一个链式比较。如果每个成对比较依次为true,则返回true。相当于(0 < 0) and (0 == 0) >>> (0) < (0 == 0) True 这等效0 < True于其值为True。 >>> (0 < 0) == 0 True 这等效False == 0于其值为True。 >>> 0 < (0 == 0) True 0 < True如上所述,与之等效的结果为True。 点击查看英文原文 >>> 0 < 0 == 0 False This is a chained comparison. It returns true if each pairwise comparison in turn is true. It is the equivalent to (0 < 0) and (0 == 0) >>> (0) < (0 == 0) True This is equivalent to 0 < True which evaluates to True. >>> (0 < 0) == 0 True This is equivalent to False == 0 which evaluates to True. >>> 0 < (0 == 0) True Equivalent to 0 < True which, as above, evaluates to True. 回答 4 查看反汇编(字节码),很明显为什么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 < 0是False,因此进行了跳转,即使堆栈中的部分甚至没有被检查,它也会False为堆栈留下a ,这是整个表达式的返回值。0 < 0 == 0== 0 因此,总而言之,答案就像对该问题的其他答案中所说的那样。 0 < 0 == 0有特殊的意义。编译器将其评估为两个术语:0 < 0和0 == 0。与任何复杂的布尔表达式一样and它们之间的一样,如果第一个失败,则甚至不会检查第二个。 希望这对我们有所启发,并且我真的希望我用来分析这种意外行为的方法会鼓励其他人将来尝试相同的方法。 点击查看英文原文 Looking at the disassembly (the bytes codes) it is obvious why 0 < 0 == 0 is False. Here is an analysis of this expression: >>>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 Notice lines 0-8: These lines check if 0 < 0 which obviously returns False onto the python stack. Now notice line 11: JUMP_IF_FALSE_OR_POP 23 This means that if 0 < 0 returns False perform a jump to line 23. Now, 0 < 0 is False, so the jump is taken, which leaves the stack with a False which is the return value for the whole expression 0 < 0 == 0, even though the == 0 part isn’t even checked. So, to conclude, the answer is like said in other answers to this question. 0 < 0 == 0 has a special meaning. The compiler evaluates this to two terms: 0 < 0 and 0 == 0. As with any complex boolean expressions with and between them, if the first fails then the second one isn’t even checked. Hopes this enlightens things up a bit, and I really hope that the method I used to analyse this unexpected behavior will encourage others to try the same in the future. 回答 5 正如其他人提到的那样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。 点击查看英文原文 As other’s mentioned x comparison_operator y comparison_operator z is syntactical sugar for (x comparison_operator y) and (y comparison_operator z) with the bonus that y is only evaluated once. So your expression 0 < 0 == 0 is really (0 < 0) and (0 == 0), which evaluates to False and True which is just False. 回答 6 也许从这个摘录文档可以帮助: 这些是所谓的“丰富比较”方法,在__cmp__()下面优先于比较运算符。运算符符号和方法名之间的对应关系如下:x<y呼叫 x.__lt__(y),x<=y呼叫x.__le__(y), x==y呼叫x.__eq__(y),x!=y和x<>y 呼叫x.__ne__(y),x>y呼叫 x.__gt__(y),和x>=y呼叫 x.__ge__(y)。 如果富比较方法NotImplemented未实现给定参数对的操作,则可能返回单例。按照惯例,False并将True其返回以进行成功比较。但是,这些方法可以返回任何值,因此,如果在布尔上下文中使用比较运算符(例如,在if语句的条件下),Python将调用bool()该值以确定结果是true还是false。 比较运算符之间没有隐含的关系。的真相x==y并不意味着那x!=y 是错误的。因此,在定义时 __eq__(),还应该定义一个,__ne__()以便操作符能够按预期运行。有关__hash__()创建可哈希对象(支持自定义比较操作并可用作字典键)的一些重要说明,请参见上的段落。 这些方法没有交换参数版本(当left参数不支持该操作但right参数支持该操作时使用);相反,__lt__()and __gt__() 是彼此的反射,__le__() and __ge__()是彼此的反射,and __eq__()and __ne__() 是自己的反射。 丰富比较方法的论点永远不会被强迫。 这些是比较,但是由于要链接比较,因此您应该知道: 可以任意链接比较,例如x < y <= z与等效x < y and y <= z,除了y仅被评估一次(但是在两种情况下,当x <y为假时,z都不被评估)。 形式上,如果a,b,c,…,y,z是表达式,而op1,op2,…,opN是比较运算符,则op1 b op2 c … y opN z等效于op1 b和b op2 c和… y opN z,除了每个表达式最多计算一次。 点击查看英文原文 maybe this excerpt from the docs can help: These are the so-called “rich comparison” methods, and are called for comparison operators in preference to __cmp__() below. The correspondence between operator symbols and method names is as follows: x<y calls x.__lt__(y), x<=y calls x.__le__(y), x==y calls x.__eq__(y), x!=y and x<>y call x.__ne__(y), x>y calls x.__gt__(y), and x>=y calls x.__ge__(y). A rich comparison method may return the singleton NotImplemented if it does not implement the operation for a given pair of arguments. By convention, False and True are returned for a successful comparison. However, these methods can return any value, so if the comparison operator is used in a Boolean context (e.g., in the condition of an if statement), Python will call bool() on the value to determine if the result is true or false. There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false. Accordingly, when defining __eq__(), one should also define __ne__() so that the operators will behave as expected. See the paragraph on __hash__() for some important notes on creating hashable objects which support custom comparison operations and are usable as dictionary keys. There are no swapped-argument versions of these methods (to be used when the left argument does not support the operation but the right argument does); rather, __lt__() and __gt__() are each other’s reflection, __le__() and __ge__() are each other’s reflection, and __eq__() and __ne__() are their own reflection. Arguments to rich comparison methods are never coerced. These were comparisons but since you are chaining comparisons you should know that: Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false). Formally, if a, b, c, …, y, z are expressions and op1, op2, …, opN are comparison operators, then a op1 b op2 c … y opN z is equivalent to a op1 b and b op2 c and … y opN z, except that each expression is evaluated at most once. 回答 7 这就是它的全部荣耀。 >>> 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 >>> 点击查看英文原文 Here it is, in all its glory. >>> 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 >>> 回答 8 我在想Python在魔术之间做得很奇怪。与1 < 2 < 3均值2 相同,介于1和3之间。 在这种情况下,我认为它正在执行[中间0]大于[左0]并等于[右0]。中间0不大于左边0,因此它的值为false。 点击查看英文原文 I’m thinking Python is doing it’s weird between magic. Same as 1 < 2 < 3 means 2 is between 1 and 3. In this case, I think it’s doing [middle 0] is greater than [left 0] and equal to [right 0]. Middle 0 is not greater than left 0, so it evaluates to false.

问题:为什么表达式0

在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

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

我的问题是在这种情况下如何运作?如何0 < 0 == 0被认为是错误的?

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

Looking into Queue.py in Python 2.6, I found this construct that I found a bit strange:

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

If maxsize is 0 the queue is never full.

My question is how does it work for this case? How 0 < 0 == 0 is considered False?

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

回答 0

我相信Python对关系运算符的序列有特殊的处理方式,以使范围比较易于表达。可以说更好0 < x <= 5比好得多(0 < x) and (x <= 5)

这些称为链接比较。这是他们文档的链接。

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

I believe Python has special case handling for sequences of relational operators to make range comparisons easy to express. It’s much nicer to be able to say 0 < x <= 5 than to say (0 < x) and (x <= 5).

These are called chained comparisons. And that’s a link to the documentation for them.

With the other cases you talk about, the parenthesis force one relational operator to be applied before the other, and so they are no longer chained comparisons. And since True and False have values as integers you get the answers you do out of the parenthesized versions.


回答 1

因为

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

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


编辑-关于Python中正确与错误的说明

在Python中TrueFalse仅仅是的实例bool,它是的子类int。换句话说,True确实只有1。

这样做的目的是,您可以像完全使用整数一样使用布尔比较的结果。这导致诸如

>>> (1==1)+(1==1)
2
>>> (2<1)<1
True

但是,只有在您对比较加括号以使它们首先被评估时,这些情况才会发生。否则,Python将扩展比较运算符。

Because

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

is False. You can chain together comparison operators and they are automatically expanded out into the pairwise comparisons.


EDIT — clarification about True and False in Python

In Python True and False are just instances of bool, which is a subclass of int. In other words, True really is just 1.

The point of this is that you can use the result of a boolean comparison exactly like an integer. This leads to confusing things like

>>> (1==1)+(1==1)
2
>>> (2<1)<1
True

But these will only happen if you parenthesise the comparisons so that they are evaluated first. Otherwise Python will expand out the comparison operators.


回答 2

您遇到的奇怪行为来自python链接条件的能力。由于发现0不小于0,因此它决定整个表达式的计算结果为false。一旦将其分解为单独的条件,就在更改功能。最初,它实际上是在测试a < b && b == c您对的原始声明a < b == c

另一个例子:

>>> 1 < 5 < 3
False

>>> (1 < 5) < 3
True

The strange behavior your experiencing comes from pythons ability to chain conditions. Since it finds 0 is not less than 0, it decides the entire expression evaluates to false. As soon as you break this apart into seperate conditions, you’re changing the functionality. It initially is essentially testing that a < b && b == c for your original statement of a < b == c.

Another example:

>>> 1 < 5 < 3
False

>>> (1 < 5) < 3
True

回答 3

>>> 0 < 0 == 0
False

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

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

这等效0 < True于其值为True。

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

这等效False == 0于其值为True。

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

0 < True如上所述,与之等效的结果为True。

>>> 0 < 0 == 0
False

This is a chained comparison. It returns true if each pairwise comparison in turn is true. It is the equivalent to (0 < 0) and (0 == 0)

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

This is equivalent to 0 < True which evaluates to True.

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

This is equivalent to False == 0 which evaluates to True.

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

Equivalent to 0 < True which, as above, evaluates to True.


回答 4

查看反汇编(字节码),很明显为什么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

注意第0-8行:这些行检查是否0 < 0明显返回False了python堆栈。

现在注意第11行:JUMP_IF_FALSE_OR_POP 23 这意味着如果0 < 0返回,则False跳到第23行。

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

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

希望这对我们有所启发,并且我真的希望我用来分析这种意外行为的方法会鼓励其他人将来尝试相同的方法。

Looking at the disassembly (the bytes codes) it is obvious why 0 < 0 == 0 is False.

Here is an analysis of this expression:

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

Notice lines 0-8: These lines check if 0 < 0 which obviously returns False onto the python stack.

Now notice line 11: JUMP_IF_FALSE_OR_POP 23 This means that if 0 < 0 returns False perform a jump to line 23.

Now, 0 < 0 is False, so the jump is taken, which leaves the stack with a False which is the return value for the whole expression 0 < 0 == 0, even though the == 0 part isn’t even checked.

So, to conclude, the answer is like said in other answers to this question. 0 < 0 == 0 has a special meaning. The compiler evaluates this to two terms: 0 < 0 and 0 == 0. As with any complex boolean expressions with and between them, if the first fails then the second one isn’t even checked.

Hopes this enlightens things up a bit, and I really hope that the method I used to analyse this unexpected behavior will encourage others to try the same in the future.


回答 5

正如其他人提到的那样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

As other’s mentioned x comparison_operator y comparison_operator z is syntactical sugar for (x comparison_operator y) and (y comparison_operator z) with the bonus that y is only evaluated once.

So your expression 0 < 0 == 0 is really (0 < 0) and (0 == 0), which evaluates to False and True which is just False.


回答 6

也许从这个摘录文档可以帮助:

这些是所谓的“丰富比较”方法,在__cmp__()下面优先于比较运算符。运算符符号和方法名之间的对应关系如下:x<y呼叫 x.__lt__(y)x<=y呼叫x.__le__(y)x==y呼叫x.__eq__(y)x!=yx<>y 呼叫x.__ne__(y)x>y呼叫 x.__gt__(y),和x>=y呼叫 x.__ge__(y)

如果富比较方法NotImplemented未实现给定参数对的操作,则可能返回单例。按照惯例,False并将True其返回以进行成功比较。但是,这些方法可以返回任何值,因此,如果在布尔上下文中使用比较运算符(例如,在if语句的条件下),Python将调用bool()该值以确定结果是true还是false。

比较运算符之间没有隐含的关系。的真相x==y并不意味着那x!=y 是错误的。因此,在定义时 __eq__(),还应该定义一个,__ne__()以便操作符能够按预期运行。有关__hash__()创建可哈希对象(支持自定义比较操作并可用作字典键)的一些重要说明,请参见上的段落。

这些方法没有交换参数版本(当left参数不支持该操作但right参数支持该操作时使用);相反,__lt__()and __gt__() 是彼此的反射,__le__() and __ge__()是彼此的反射,and __eq__()and __ne__() 是自己的反射。

丰富比较方法的论点永远不会被强迫。

这些是比较,但是由于要链接比较,因此您应该知道:

可以任意链接比较,例如x < y <= z与等效x < y and y <= z,除了y仅被评估一次(但是在两种情况下,当x <y为假时,z都不被评估)。

形式上,如果a,b,c,…,y,z是表达式,而op1,op2,…,opN是比较运算符,则op1 b op2 c … y opN z等效于op1 b和b op2 c和… y opN z,除了每个表达式最多计算一次。

maybe this excerpt from the docs can help:

These are the so-called “rich comparison” methods, and are called for comparison operators in preference to __cmp__() below. The correspondence between operator symbols and method names is as follows: x<y calls x.__lt__(y), x<=y calls x.__le__(y), x==y calls x.__eq__(y), x!=y and x<>y call x.__ne__(y), x>y calls x.__gt__(y), and x>=y calls x.__ge__(y).

A rich comparison method may return the singleton NotImplemented if it does not implement the operation for a given pair of arguments. By convention, False and True are returned for a successful comparison. However, these methods can return any value, so if the comparison operator is used in a Boolean context (e.g., in the condition of an if statement), Python will call bool() on the value to determine if the result is true or false.

There are no implied relationships among the comparison operators. The truth of x==y does not imply that x!=y is false. Accordingly, when defining __eq__(), one should also define __ne__() so that the operators will behave as expected. See the paragraph on __hash__() for some important notes on creating hashable objects which support custom comparison operations and are usable as dictionary keys.

There are no swapped-argument versions of these methods (to be used when the left argument does not support the operation but the right argument does); rather, __lt__() and __gt__() are each other’s reflection, __le__() and __ge__() are each other’s reflection, and __eq__() and __ne__() are their own reflection.

Arguments to rich comparison methods are never coerced.

These were comparisons but since you are chaining comparisons you should know that:

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

Formally, if a, b, c, …, y, z are expressions and op1, op2, …, opN are comparison operators, then a op1 b op2 c … y opN z is equivalent to a op1 b and b op2 c and … y opN z, except that each expression is evaluated at most once.


回答 7

这就是它的全部荣耀。

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

Here it is, in all its glory.

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

回答 8

我在想Python在魔术之间做得很奇怪。与1 < 2 < 3均值2 相同,介于1和3之间。

在这种情况下,我认为它正在执行[中间0]大于[左0]并等于[右0]。中间0不大于左边0,因此它的值为false。

I’m thinking Python is doing it’s weird between magic. Same as 1 < 2 < 3 means 2 is between 1 and 3.

In this case, I think it’s doing [middle 0] is greater than [left 0] and equal to [right 0]. Middle 0 is not greater than left 0, so it evaluates to false.