python3 未定义 __ne__ returns 与定义相同的值 __eq__

python3 undefined __ne__ returns same value as defined __eq__

我有一个 class MyClass,其中 __eq__ 定义如下:

def __eq__(self, other):
        try:
            other = MyClass(other)
        except Exception as e:
            raise ValueError(f"MyClass.__eq__ failed: {other} doesn't appear to be a valid MyClass type. \n", e )

        prefix_i1 = re.findall("[ab]" , self       )
        prefix_i2 = re.findall("[ab]" , other )
        if len( set( prefix_i1 + prefix_i2 ) ) > 1:
            return False    # ie: "a07" != "b07" BUT  "k07" == "b07"
        else:
            return self.num_string == other.num_string   # eg: "i3" == "i03"

哪里

self.num_string = "".join(filter(str.isdigit, self               )).zfill(2)

没想到,我得到了这个结果:

> MyClass('b05') == MyClass('i05')
True
> MyClass('b05') != MyClass('i05')
True

我认为 __ne__ 默认是 not __eq__ 并且不鼓励明确定义它,因为 Python 3.

我做错了什么?

这是一个最小的可重现示例:

import re

class MyClass(str):
    def __new__(cls, *args, **kwargs):
        if  args[0] is None:
            return str.__new__(cls, '' )
        if not ( isinstance(args[0], int) or 
                 ( isinstance(args[0], str) and re.match("[iab]?[0-9]{1,2}", args[0].lower()) ) ):
            raise ValueError("MyClass failed because the provided input '{}' is not valid... .".format(args[0])) 
        lower_str_input = str(args[0]).lower()
        return str.__new__(cls, lower_str_input ) 
    def __init__(self, input_string=''):
      self.num_string = "".join(filter(str.isdigit, self               )).zfill(2)
    def __eq__(self, other):
        try:
            other = MyClass(other)
        except Exception as e:
            raise ValueError("MyClass.__eq__ failed" )
        prefix_i1 = re.findall("[ab]" , self       )
        prefix_i2 = re.findall("[ab]" , other )
        if len( set( prefix_i1 + prefix_i2 ) ) > 1:
            return False    # ie: "a07" != "b07" BUT  "k07" == "b07"
        else:
            return self.num_string == other.num_string   # eg: "i3" == "i03"

MyClass('b05') == MyClass('i05')
MyClass('b05') != MyClass('i05')

I thought __ne__ was by default not __eq__ and defining it explicitly was discouraged since Python 3.

为了你自己的 类,是的。默认情况下,它们将派生自 object,后者实现了该逻辑。

然而,built-ins(以及由此派生的所有内容)可能有点奇怪。

这是一个更简单的例子:

... class x(str):
...     def __eq__(self, other):
...         print('eq called')
...         return str.__eq__(self, other)
... 
>>> x('foo') != 'foo'
False

答案正确,但未调用 __eq__(因此没有打印消息)。这个答案来自str.__ne__,它(显然)是单独实现的(不是__eq__)。