当前位置:   article > 正文

【Python面向对象编程】第13篇 特殊方法之__hash___python 实验对象的 hash 方法

python 实验对象的 hash 方法

本篇介绍 Python hash() 函数,以及如何覆盖自定义类中的 __hash__ 方法。

hash() 函数简介

以下是一个简单的 Person 类,包含 name 和 age 两个属性:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
  • 1
  • 2
  • 3
  • 4
'
运行

我们创建两个 Person 类的实例:

p1 = Person('John', 22)
p2 = Person('Jane', 22)
  • 1
  • 2

然后打印 p1 和 p2 的哈希值:

print(hash(p1))
print(hash(p2))
  • 1
  • 2

输出结果如下:

182520477297
182520477303
  • 1
  • 2
'
运行

hash() 函数接受一个对象作为参数,返回一个整数形式的哈希值。当我们将对象传递给 hash() 函数时,Python 会执行该对象的 __hash__ 方法。以下示例将 p1 传递给 hash() 函数:

hash(p1)
  • 1

Python 会调用 p1 对象的 __hash__ 方法:

p1.__hash__()
  • 1

默认情况下,__hash__ 方法返回对象的标识符,而 __eq__ 方法在两个对象相同时返回 True。如果想要覆盖这个默认行为,我们可以实现 __hash__ 方法和 __eq__ 方法。

覆盖 __hash__ 方法

如果一个类覆盖了 __eq__ 方法,该类的对象就会变成不可哈希(unhashable)对象。也就是说,我们无法在映射类型中使用这些对象。例如,它们不能作为字典的键或集合中的元素。

下面的示例为 Person 类实现了 __eq__ 方法:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        return isinstance(other, Person) and self.age == other.age
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
'
运行

如果我们在集合中使用 Person 对象,将会返回错误,例如:

members = {
    Person('John', 22),
    Person('Jane', 22)
}
TypeError: unhashable type: 'Person'
  • 1
  • 2
  • 3
  • 4
  • 5

另外,Person 对象失去了哈希功能,因为我们实现了 __eq__ 方法,__hash__ 方法被设置为 None。例如:

hash(Person('John', 22))
TypeError: unhashable type: 'Person'
  • 1
  • 2

为了使得 Person 类可哈希,我们还需要实现 __hash__ 方法:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):
        return isinstance(other, Person) and self.age == other.age

    def __hash__(self):
        return hash(self.age)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
'
运行

现在,Person 类既支持基于 age 的等值比较,又具有哈希功能。

为了使得 Person 能够正常用于字典这种数据结构,类的哈希值必须具有不可变性。为此,我们可以将 age 定义为只读属性:

class Person:
    def __init__(self, name, age):
        self.name = name
        self._age = age

    @property
    def age(self):
        return self._age

    def __eq__(self, other):
        return isinstance(other, Person) and self.age == other.age

    def __hash__(self):
        return hash(self.age)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
'
运行

总结

  • 默认情况下,__hash__ 方法返回对象的 ID,__eq__ 方法使用 is 操作符进行比较。
  • 如果实现了 __eq__ 方法,Python 会将 __hash__ 方法设置为 None,除非实现了自定义的 __hash__ 方法。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/812096
推荐阅读
相关标签
  

闽ICP备14008679号