【问题标题】:Python: Raise error when comparing objects of different type for equalityPython:比较不同类型的对象是否相等时引发错误
【发布时间】:2021-12-31 12:20:39
【问题描述】:

据我了解,在 Python 中,比较两个不同类的实例是否相等:

  • 评估第一个实例的__eq__方法并返回结果
  • 除非结果是NotImplemented,然后评估第二个实例的__eq__方法并返回结果
  • 除非结果是NotImplemented,然后比较对象标识并返回结果(为False)

我多次遇到引发异常的情况,这些情况可以帮助我发现代码中的错误。 Martijn Pieters 在this post 中勾勒出了一种实现方式,但也提到它是非 Python 的。

除了不符合Python语言之外,这种方法是否存在实际问题?

【问题讨论】:

  • 你在使用 linter 吗?如果是这样,也许您可​​以将其配置为在比较不同类型的对象时发出警告?
  • the post you linked to 的选项 1. 恕我直言,您应该仅在确实需要时才使用它。我刚刚添加了一个comment there 来强调一个事实,即在 Python 中基本上构建多态性确实是非常可取的。
  • @md2perpe 你说得对,静态类型检查器可能也能解决问题。

标签: python


【解决方案1】:

严格来说,它当然是“unpythonic”,因为 Python 鼓励鸭子类型和严格的子类型。但我个人更喜欢严格类型的接口,所以我抛出TypeErrors。从来没有任何问题,但我不能明确地说你永远不会有任何问题。

理论上,如果您发现自己需要使用像 list[Optional[YourType]] 这样的混合类型容器,然后可能间接比较它的元素,例如在构造 set(your_mixed_list) 时,我可以想象这是一个问题。

【讨论】:

    【解决方案2】:

    这会导致具有相同哈希的混合键的字典出现问题。字典允许多个键具有相同的哈希值,然后进行相等性检查以区分键。见https://stackoverflow.com/a/9022835/1217284

    以下脚本演示了这一点,当使用 Misbehaving1 类时它会失败:

    #!/usr/bin/env python3
    
    class Behaving1:
        def __init__(self, value):
            self.value = value
        def __hash__(self):
            return 7
    
    class Behaving2:
        def __init__(self, value):
            self.value = value
        def __hash__(self):
            return 7
        def __eq__(self, other):
            if not (isinstance(other, type(self)) or isinstance(self, type(other))):
                return NotImplemented
            return self.value == other.value
    
    
    class MisBehaving1:
        def __init__(self, value):
            self.value = value
        def __hash__(self):
            return 7
        def __eq__(self, other):
            if not (isinstance(other, type(self)) or isinstance(self, type(other))):
                raise TypeError(f"Cannot compare {self} of type {type(self)} with {other} of type {type(other)}")
            return self.value == other.value
    
    
    d = {Behaving1(5): 'hello', Behaving2(4): 'world'}
    print(d)
    
    dd = {Behaving1(5): 'hello', MisBehaving1(4): 'world'}
    print(dd)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-07
      • 2017-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多