Python中的可哈希与不可哈希对象详解

在复习可变对象和不可变对象时,学到了这个内容


1. 前置知识:哈希是什么

哈希(Hashing)是一种将任意大小的数据转换成固定大小的数据的过程。这种转换通过哈希函数实现,它接收输入(或“消息”),并返回一个通常具有固定长度的字符串,这个字符串被称为哈希值或哈希码。哈希的主要用途包括数据的快速查找、数据完整性校验、以及安全应用中的加密技术。

哈希的关键特点是:

  • 效率高:哈希函数设计为能够快速处理大量数据。
  • 确定性:对于同一输入总是产生相同的输出。
  • 随机分布:哈希值应均匀且随机分布,减少冲突。
  • 不可逆性:理想的哈希函数使得从哈希值恢复原始输入极其困难。

2. 可哈希和不可哈希对象的定义

2.1可哈希

可哈希对象是指其生命周期内具有不变的哈希值的对象。这些对象可以作为字典的键或者集合的元素。整数、浮点数、字符串和元组都是可哈希的。

整数的哈希值

x = 10
print(hash(x))  # 输出:10的哈希值

用内置的hash()函数来获取一个整数的哈希值。

2.2 不可哈希

不可哈希对象是指内容可以更改的对象,因此哈希值也可能会变。列表和字典是典型的不可哈希对象。

列表的不可哈希性

my_list = [1, 2, 3]
try:
    print(hash(my_list))
except TypeError as e:
    print(e)  # 输出错误信息,指出列表是不可哈希的

由于列表是可变的,Python不允许对其进行哈希。所以尝试哈希列表将抛出一个TypeError。

3. 对象的哈希方法

3.1 自定义对象的哈希方法

可哈希对象需要实现__hash__()方法,该方法返回对象的哈希值。如果对象是可变的,则应返回None,表示对象不可哈希。

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

    def __hash__(self):
        return hash(self.name)  # 基于名字的哈希值

person = Person('Alice')
print(hash(person))  # 输出:Alice的哈希值

定义了一个Person类,重写__hash__()方法使其实例可哈希。哈希函数基于人的名字来计算哈希值,根据对象的某个不变属性来提供一个一致的哈希值。

3.2 可哈希性与等价性

如果两个对象的哈希值相同,它们首先被视为可能相等,然后通过__eq__()方法进行进一步的比较来确定是否真的相等。

实现等价性

class Product:
    def __init__(self, id, name):
        self.id = id
        self.name = name

    def __hash__(self):
        return hash(self.id)

    def __eq__(self, other):
        return self.id == other.id

product1 = Product(1, 'Apple')
product2 = Product(1, 'Apple')
print(hash(product1) == hash(product2))  # 输出:True
print(product1 == product2)  # 输出:True

Product类通过id属性来定义其哈希方法和等价性检测。只要两个产品的id相同,就被认为是相等的,这说明了在自定义类中如何同时实现__hash__()和__eq__()方法来保证对象可以被正确地用于字典键或集合元素。

3.3 哈希值的用途

哈希值用于快速比较对象是否相同,是字典和集合高效性的关键。

字典中使用哈希值

my_dict = {person: 'Engineer'}
print(my_dict[person])  # 输出:'Engineer'

只有可哈希对象才可以作为字典的键

推荐

推荐我的相关专栏:

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Peter-Lu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值