首页 > 后端开发 > Python教程 > 如何确保自定义 Python 类的一致且稳健的等价比较,尤其是在处理子类和集合时?

如何确保自定义 Python 类的一致且稳健的等价比较,尤其是在处理子类和集合时?

Linda Hamilton
发布: 2024-11-09 04:50:02
原创
432 人浏览过

How do you ensure consistent and robust equivalence comparisons for custom Python classes, especially when dealing with subclasses and sets?

Python 类中等价比较的优雅方法

在 Python 中,自定义类可以实现 __eq__ 和 __ne__ 方法来定义 == 和 != 运算符的等价性,分别。虽然比较字典属性的传统方法很简单,但它存在一定的局限性。

更精致的方法

考虑以下场景:

class Number:
    def __init__(self, number):
        self.number = number

n1 = Number(1)
n2 = Number(1)

# Default comparison fails: they are different objects
assert n1 != n2
登录后复制

解决此问题,我们可以重写 __eq__ 方法:

class Number:
    def __init__(self, number):
        self.number = number

    def __eq__(self, other):
        if isinstance(other, Number):
            return self.number == other.number
        return False
登录后复制

但是,对于 Python 2,我们还需要实现 __ne__ 以确保交换行为:

class Number:
    def __init__(self, number):
        self.number = number

    def __eq__(self, other):
        if isinstance(other, Number):
            return self.number == other.number
        return False

    def __ne__(self, other):
        return not self.__eq__(other)
登录后复制

这确保 n1 == n2 按预期计算为 True。

子类等价

引入子类会使等价比较复杂化:

class SubNumber(Number):
    pass

n3 = SubNumber(1)

# Subclass comparison fails for classic-style classes
assert n1 == n3  # False (for classic-style classes)
assert n3 == n1  # True

# Non-commutative comparison
assert n1 != n3  # True (for classic-style classes)
assert n3 != n1  # False
登录后复制

对于经典风格的类,比较方法根据第一个操作数的类型调用,导致不可交换的行为。为了解决这个问题,我们可以为不支持的操作数类型返回 NotImplemented,它将比较委托给其他操作数的方法:

def __eq__(self, other):
    if isinstance(other, Number):
        return self.number == other.number
    return NotImplemented
登录后复制

散列和集合

最后,请注意,集合使用对象标识符散列,这可能会导致不正确的结果:

assert len(set([n1, n2, n3])) == 3  # Incorrectly reports 3 unique numbers
登录后复制

要解决此问题,我们可以覆盖__hash__ 方法:

def __hash__(self):
    return hash(tuple(sorted(self.__dict__.items())))
登录后复制

通过这些增强功能,等价性和唯一性行为变得正确且一致,确保集合中的稳健比较和准确表示:

assert len(set([n1, n2, n3])) == 1
assert len(set([n1, n2, n3, n4])) == 2
登录后复制

以上是如何确保自定义 Python 类的一致且稳健的等价比较,尤其是在处理子类和集合时?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板