Python 的 unhashable type 错误分析及解决

简介: Python 的 unhashable type 错误分析及解决

没错,玩自动化测试时,又报错了。

image.png

日常测试中,经常会使用py的 set 和 dict,set 是用 dict 实现,因为本身 dict 的 key 就是会被去重,value 设置为 None 即可作为 set 使用。


Python 中的 dict 内部使用了哈希表的方式实现,所以对于 key 的要求就是需要计算哈希值。在 Python 的类型体系中,有些类型是支持计算哈希值,有些并不支持。所以我们可以知道,使用不支持计算哈希值的类型作为 dict 或 set 的 key 就会报错。

image.png

错误案例

以下皆报错 TypeError: unhashable type: 'list'

# list 作为 dict 的 key
key = ["news", "hot"]
news = {}
news[key] = ["news_1", "news_2"]
# list 作为 set 的 key 来去重
categories = [["news", "hot"], ["sports", "nba"]]
categories = set(categories)

分析

我们现在知道了这个错误的原因,那么 Python 内置类型中哪些支持哈希计算,哪些不支持了。

下面我们测试一下 Python 内置的类型。

import sys
def check_hash(x):
    if x.__hash__ is not None:
        print type(x), 'hashable:', hash(x)
        return True
    else:
        print type(x), 'unhashable'
        return False
# int
i = 5
check_hash(i)
# long
l = sys.maxint + 1
check_hash(l)
# float
f = 0.5
check_hash(f)
# string
s = "hello"
check_hash(s)
# unicode
u = u"中国"
check_hash(u)
# tuple
t = (i, l, f, s, u)
check_hash(t)
# object
o = object()
check_hash(o)
# list
l1 = [i, l, f, s, u]
check_hash(l1)
# set
s1 = {i, l, f, s, u}
check_hash(s1)
# dict
d1 = {s: i, u: l}
check_hash(d1)
# output:
<type 'int'> hashable: 5
<type 'long'> hashable: -9223372036854775808
<type 'float'> hashable: 1073741824
<type 'str'> hashable: 840651671246116861
<type 'unicode'> hashable: 2561679356228032696
<type 'tuple'> hashable: 1778989336750665947
<type 'object'> hashable: 270043150
<type 'list'> unhashable
<type 'set'> unhashable
<type 'dict'> unhashable

set、list、dict 三个类型是不可哈希的。对于可变的类型计算哈希值是不可靠的,当数据发生变化时哈希值也要变化。哈希计算的意义在于用哈希值来区分变量,哈希值会随着变量内容而变化,所以对于这类可变类型来说,不支持哈希值是合理的。


下面介绍下上述示例代码的一些细节,对于 Python 的深入理解有一定帮助。


定义 set

定义 set 的方法,这里需要单独说一下。set 有多种定义的方法,一般使用 set(list) 或 set(tuple) 的方式来定义,但是还有个花括号的方法可以定义,这个大家使用的较少会被忽略,就是上述示例中的方式。

l = ['a', 'b', 'a', 'c']
s = set(l)
# 使用花括号来定义
s = {'a', 'b', 'a', 'c'}


参考

http://icejoywoo.github.io/2019/03/16/python-unhashable-type-error.html


目录
相关文章
|
2天前
|
算法 搜索推荐 开发者
解锁Python代码的速度之谜:性能瓶颈分析与优化实践
探索Python性能优化,关注解释器开销、GIL、数据结构选择及I/O操作。使用cProfile和line_profiler定位瓶颈,通过Cython减少解释器影响,多进程避开GIL,优化算法与数据结构,以及借助asyncio提升I/O效率。通过精准优化,Python可应对高性能计算挑战。【6月更文挑战第15天】
10 1
|
3天前
|
数据采集 存储 数据挖掘
Python网络爬虫实战:抓取并分析网页数据
使用Python的`requests`和`BeautifulSoup`,本文演示了一个简单的网络爬虫,抓取天气网站数据并进行分析。步骤包括发送HTTP请求获取HTML,解析HTML提取温度和湿度信息,以及计算平均温度。注意事项涉及遵守robots.txt、控制请求频率及处理动态内容。此基础爬虫展示了数据自动收集和初步分析的基础流程。【6月更文挑战第14天】
58 9
|
4天前
|
数据采集 机器学习/深度学习 数据可视化
数据挖掘实战:Python在金融数据分析中的应用案例
Python在金融数据分析中扮演关键角色,用于预测市场趋势和风险管理。本文通过案例展示了使用Python库(如pandas、numpy、matplotlib等)进行数据获取、清洗、分析和建立预测模型,例如计算苹果公司(AAPL)股票的简单移动平均线,以展示基本流程。此示例为更复杂的金融建模奠定了基础。【6月更文挑战第13天】
20 3
|
5天前
|
机器学习/深度学习 数据采集 分布式计算
如何用Python处理大数据分析?
【6月更文挑战第14天】如何用Python处理大数据分析?
19 4
|
5天前
|
机器学习/深度学习 存储 监控
基于YOLOv8深度学习的无人机视角高精度太阳能电池板检测与分析系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割
基于YOLOv8深度学习的无人机视角高精度太阳能电池板检测与分析系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标分割
|
5天前
|
机器学习/深度学习 存储 计算机视觉
基于YOLOv8深度学习的智能道路裂缝检测与分析系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测、目标分割(2)
基于YOLOv8深度学习的智能道路裂缝检测与分析系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测、目标分割
|
5天前
|
机器学习/深度学习 存储 安全
基于YOLOv8深度学习的智能道路裂缝检测与分析系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测、目标分割(1)
基于YOLOv8深度学习的智能道路裂缝检测与分析系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测、目标分割
|
7天前
|
JSON 数据挖掘 API
数据分析实战丨基于pygal与requests分析GitHub最受欢迎的Python库
数据分析实战丨基于pygal与requests分析GitHub最受欢迎的Python库
18 2
|
9天前
|
存储 算法 数据挖掘
LeetCode 题目 43:字符串相乘 多种算法分析对比 【python】
LeetCode 题目 43:字符串相乘 多种算法分析对比 【python】
|
9天前
|
供应链 数据可视化 搜索推荐
【python plotly库介绍】从视觉到洞见:桑基图在业务分析中的应用【保姆级教程过于详细珍藏版】
【python plotly库介绍】从视觉到洞见:桑基图在业务分析中的应用【保姆级教程过于详细珍藏版】