从__eq__返回NotImplemented [英] Returning NotImplemented from __eq__

查看:65
本文介绍了从__eq__返回NotImplemented的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在python 3中从 __ eq __ 特殊方法返回 NotImplemented 的结果是什么(如果重要的话,返回3.5)?

What's the result of returning NotImplemented from __eq__ special method in python 3 (well 3.5 if it matters)?

文档不清晰; 我发现的唯一相关文本仅含糊地提及其他一些后备 :

The documentation isn't clear; the only relevant text I found only vaguely refers to "some other fallback":


返回 NotImplemented 时,解释器将尝试在其他类型,或其他一些后备情况,具体取决于运营商。如果所有尝试的操作均返回 NotImplemented ,则解释器将引发适当的异常。有关更多详细信息,请参见实现算术运算

When NotImplemented is returned, the interpreter will then try the reflected operation on the other type, or some other fallback, depending on the operator. If all attempted operations return NotImplemented, the interpreter will raise an appropriate exception. See Implementing the arithmetic operations for more details.

不幸的是,更多详细信息链接并未提及 __ eq __

Unfortunately, the "more details" link doesn't mention __eq__ at all.

我阅读此摘录建议,下面的代码应引发适当的异常,但不会:

My reading of this excerpt suggests that the code below should raise an "appropriate exception", but it does not:

class A:
  def __eq__(self, other):
    return NotImplemented

class B:
  def __eq__(self, other):
    return NotImplemented

# docs seems to say these lines should raise "an appropriate exception"
# but no exception is raised
a = A()
b = B()
a == b # evaluates as unequal
a == a # evaluates as equal

通过实验,我认为从 __ eq __ NotImplemented >,解释器的行为就像 __ e q __ 并不是最初定义的(特别是,它首先交换参数,如果不能解决问题,则使用默认的 __ eq __ ,如果两个对象具有相同的标识,则计算结果为相等。如果是这样,我可以在文档中哪里找到对该行为的确认?

From experimenting, I think that when NotImplemented is returned from __eq__, the interpreter behaves as if __eq__ wasn't defined in the first place (specifically, it first swaps the arguments, and if that doesn't resolve the issue, it compares using the default __eq__ that evaluates "equal" if the two objects have the same identity). If that's the case, where in the documentation can I find the confirmation of this behavior?

编辑:请参见 Python问题28785

推荐答案

实际上 = = != 检查工作与排序比较运算符(< 等类似) ),只是他们没有提出适当的例外情况,而是退回到身份比较。唯一的区别。

Actually the == and != check work identical to the ordering comparison operators (< and similar) except that they don't raise the appropriate exception but fall-back to identity comparison. That's the only difference.

CPython源代码。我将包括该源代码的Python版本(至少在可能的范围内):

This can be easily seen in the CPython source code. I will include a Python version of that source code (at least as far as it's possible):

_mirrored_op = {'__eq__': '__eq__',  # a == b => b == a
                '__ne__': '__ne__',  # a != b => b != a
                '__lt__': '__ge__',  # a < b  => b >= a
                '__le__': '__gt__',  # a <= b => b > a
                '__ge__': '__lt__',  # a >= b => b < a
                '__gt__': '__le__'   # a > b  => b <= a
               }

def richcmp(v, w, op):
    checked_reverse = 0
    # If the second operand is a true subclass of the first one start with
    # a reversed operation.
    if type(v) != type(w) and issubclass(type(w), type(v)) and hasattr(w, op):
        checked_reverse = 1
        res = getattr(w, _mirrored_op[op])(v)     # reversed
        if res is not NotImplemented:
            return res
    # Always try the not-reversed operation
    if hasattr(v, op):
        res = getattr(v, op)(w)      # normal
        if res is not NotImplemented:
            return res
    # If we haven't already tried the reversed operation try it now!
    if not checked_reverse and hasattr(w, op):
        res = getattr(w, _mirrored_op[op])(v)      # reversed
        if res is not NotImplemented:
            return res
    # Raise exception for ordering comparisons but use object identity in 
    # case we compare for equality or inequality
    if op == '__eq__':
        res = v is w
    elif op == '__ne__':
        res = v is not w
    else:
        raise TypeError('sth')

    return res

并调用 a == b 然后计算为 richcmp(a,b,'__eq __') if op =='__eq __'是使您的 a == b 返回<$ c $的特殊情况c> False (因为它们不是相同的对象),并且您的 a == a 返回 True (因为它们是。)。

and calling a == b then evaluates as richcmp(a, b, '__eq__'). The if op == '__eq__' is the special case that makes your a == b return False (because they aren't identical objects) and your a == a return True (because they are).

但是Python 2.x中的行为完全不同。在退回身份比较之前,您最多可以进行4次(甚至我不记得有6次)比较!

However the behaviour in Python 2.x was completly different. You could have up to 4 (or even 6, I don't remember exactly) comparisons before falling back to identity comparison!

这篇关于从__eq__返回NotImplemented的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆