Python中的"反转"比较运算符

bli*_*587 6 python comparison

class Inner():

    def __init__(self, x):
        self.x = x

    def __eq__(self, other):
        if isinstance(other, Inner):
            return self.x == other.x
        else:
            raise TypeError("Incorrect type to compare")

class Outer():

    def __init__(self, y):
        self.y = Inner(y)

    def __eq__(self, other):
        if isinstance(other, Outer):
            return self.y == other.y
        elif isinstance(other, Inner):
            return self.y == other
        else:
            raise TypeError("Incorrect type to compare")


if __name__ == "__main__":

    a = Outer(1)
    b = Inner(1)

    print(a == b) # ok no problem
    print(b == a) # This will raise a type error
Run Code Online (Sandbox Code Playgroud)

在示例中,我有内部和外部类.我无法控制内部工具只是想模拟这种情况.我只能控制Outer的行为.我希望外部实例能够与内部实例进行比较(而不仅仅是相等).使用给定的实现只有第一个比较有效,因为调用Outer的__eq__方法允许与外部和内部实例进行比较,但第二个调用Inner的__eq__,这将不允许与外部进行比较 - 哎呀它不知道外部存在为什么应该它很难实现它.有没有办法让第二种类型的比较工作,类似于__radd__和这样的功能.我知道,例如在C++中,您可以使用内联运算符定义来解决此问题,但我们在Python中没有这样做.

jon*_*rpe 3

不要说得太细:它Inner.__eq__已经坏了。至少,它不应该抛出错误return NotImplemented,这将允许 Python 尝试反向比较:

NotImplemented返回时,解释器将尝试对其他类型进行反射操作,或其他一些回退,具体取决于运算符。如果所有尝试的操作都返回 NotImplemented,解释器将引发适当的异常。

更好的是,它会使用“鸭子类型”,而不是坚持使用特定的类(除非该类,而不是其接口,是比较中明确重要的部分):

def __eq__(self, other):
    try:
        return self.x == other.x
    except AttributeError:
        return NotImplemented
Run Code Online (Sandbox Code Playgroud)

但是,正如您所说您无法控制这一点,您将必须手动实现类似的功能,例如:

def compare(a, b):
    """'Safe' comparison between two objects."""
    try:
        return a == b
    except TypeError:
        return b == a
Run Code Online (Sandbox Code Playgroud)

因为Python的数据模型__req__中不存在这样的东西。