Python 中主要数据类型分类及特性总结(附:可哈希 (Hashable) 与 不可哈希 (Unhashable) 详解)

本文系统总结了Python中的数据类型分类及特性。


主要内容包括:

  1. 数据类型分类:基本类型(int/float/str等)、序列类型(list/tuple/range)、映射类型(dict)、集合类型(set/frozenset)和二进制序列类型(bytes/bytearray);
  2. 类型特性对比:可变性(list/dict可变,tuple/str不可变)、有序性(list有序,set无序)和可哈希性(可哈希类型可作为字典键);
  3. 可哈希性详解:定义了可哈希对象的条件(不可变、有哈希值、可比较相等),列举了常见可哈希与不可哈希类型,并说明了可哈希性的实际应用场景;
  4. 类型转换与判断方法。

全文通过对比表格和示例代码,清晰展示了Python数据类型的核心特性与使用要点。


Python 中主要数据类型分类总结


一、基本数据类型

类型 名称 示例 特点 可变性
int 整数 42, -10, 0b1010 任意精度,无范围限制 不可变
float 浮点数 3.14, -0.5, 1.2e-5 双精度浮点数 不可变
complex 复数 3+4j, 1.2-0.5j 实部+虚部 不可变
bool 布尔型 True, False 只有两个值,是int子类 不可变
str 字符串 "Hello", 'Python', """多行""" Unicode字符序列 不可变
NoneType 空值 None 表示空或不存在的值 不可变

二、序列类型

类型 名称 示例 特点 可变性 有序性
list 列表 [1, 2, 3], ['a', 'b'] 可存放任意类型,功能强大 可变 有序
tuple 元组 (1, 2, 3), ('a',) 轻量级不可变序列 不可变 有序
range 范围 range(5), range(1,10,2) 整数序列,节省内存 不可变 有序

三、映射类型

类型 名称 示例 特点 可变性 有序性
dict 字典 {'name':'Tom', 'age':18} 键值对存储,键必须可哈希 可变 Python3.7+有序

四、集合类型

类型 名称 示例 特点 可变性 有序性
set 集合 {1, 2, 3}, set([1,2,2]) 元素唯一,去重 可变 无序
frozenset 冻结集合 frozenset([1,2,3]) 不可变版本的集合 不可变 无序

五、二进制序列类型

类型 名称 示例 特点 可变性
bytes 字节串 b'hello', bytes([65,66]) 0-255的整数序列 不可变
bytearray 字节数组 bytearray(b'hello') 可修改的字节序列 可变
memoryview 内存视图 memoryview(b'hello') 直接访问内存数据 可变

六、各类型对比速查

可变 vs 不可变

可变类型 (Mutable) 不可变类型 (Immutable)
list int
dict float
set bool
bytearray str
自定义类实例(默认) tuple
frozenset
bytes
range

有序 vs 无序

有序类型 (Ordered) 无序类型 (Unordered)
list set
tuple frozenset
str dict (Python3.7前)
range
dict (Python3.7+)

可哈希 vs 不可哈希

可哈希类型(可作为字典键) 不可哈希类型
int, float, bool list
str dict
tuple(元素都哈希) set
frozenset bytearray
None

七、类型判断与转换

操作 示例 说明
类型判断 isinstance(5, int) 推荐使用,支持继承
类型判断 type(5) is int 精确判断,不考虑继承
类型转换 list((1,2,3)) 元组转列表
类型转换 tuple([1,2,3]) 列表转元组
类型转换 set([1,2,2,3]) 列表转集合(去重)
类型转换 dict([(1,'a'),(2,'b')]) 键值对序列转字典
类型转换 str(123) 转字符串
类型转换 int("123") 字符串转整数

八、各类型字面量速查

类型 字面量示例
int 42, 0xFF(十六进制), 0o12(八进制), 0b1010(二进制)
float 3.14, 1.2e-5
complex 3+4j
str '单引号', "双引号", '''三单引号''', """三双引号"""
list [1, 2, 3]
tuple (1, 2, 3)1, 2, 3
dict {'key': 'value'}
set {1, 2, 3}
bool True, False
None None

提示 :Python 是动态强类型语言,变量无需声明类型,但不同类型之间通常不会自动转换。


可哈希 (Hashable) 与 不可哈希 (Unhashable) 详解


一、什么是哈希?


哈希 是将任意大小的数据(如字符串、数字)通过哈希函数 转换成固定长度的唯一标识(哈希值)的过程。


python

python 复制代码
# 哈希值示例
hash(42)      # 输出: 42
hash("hello") # 输出: -2091548855179221912
hash((1,2,3)) # 输出: 529344067295497451

二、可哈希类型的特征

一个对象是可哈希的,需要满足以下条件:

  1. 有哈希值 - 实现 __hash__() 方法

  2. 可比较相等 - 实现 __eq__() 方法

  3. 不可变 - 创建后内容不能改变


三、常见可哈希与不可哈希类型

类型 可哈希? 原因
int ✅ 是 不可变
float ✅ 是 不可变
bool ✅ 是 不可变
str ✅ 是 不可变
tuple ✅ 是 不可变(前提:内部元素也都可哈希)
frozenset ✅ 是 不可变
None ✅ 是 单例对象
list ❌ 否 可变,内容可改变
dict ❌ 否 可变
set ❌ 否 可变
bytearray ❌ 否 可变

四、为什么需要可哈希?

可哈希对象可以:

  • 作为字典的键 (dict key)

  • 作为集合的元素 (set element)

python

python 复制代码
# ✅ 正确:使用可哈希类型作为字典键
d = {
    1: "整数键",           # int 可哈希
    "name": "字符串键",    # str 可哈希
    (1,2): "元组键"        # tuple 可哈希
}

# ✅ 正确:使用可哈希类型作为集合元素
s = {1, 2, 3, "a", (4,5)}

# ❌ 错误:使用不可哈希类型作为字典键
d = {[1,2]: "列表键"}  
# TypeError: unhashable type: 'list'

# ❌ 错误:使用不可哈希类型作为集合元素
s = {[1,2], [3,4]}
# TypeError: unhashable type: 'list'

五、特殊情况:元组的可哈希性

元组本身不可变,但它的可哈希性取决于内部元素

python

python 复制代码
# ✅ 元组内都是可哈希元素 → 元组可哈希
t1 = (1, 2, "a")
hash(t1)  # 成功

# ❌ 元组内包含不可哈希元素 → 元组不可哈希
t2 = (1, [2, 3], "a")
hash(t2)  # TypeError: unhashable type: 'list'

六、如何判断对象是否可哈希?

python

python 复制代码
# 方法1:使用 hash() 函数测试
def is_hashable(obj):
    try:
        hash(obj)
        return True
    except TypeError:
        return False

print(is_hashable(42))        # True
print(is_hashable("hello"))   # True
print(is_hashable([1,2]))     # False
print(is_hashable({1,2}))     # False

# 方法2:使用 collections.abc.Hashable
from collections.abc import Hashable

print(isinstance(42, Hashable))      # True
print(isinstance([1,2], Hashable))   # False

七、实际应用场景

场景1:去重时的问题

python

python 复制代码
data = [1, 2, 2, [3,4], [3,4], 5]

# ❌ 错误:直接对包含列表的列表用 set() 去重
unique = set(data)  # TypeError: unhashable type: 'list'

# ✅ 解决:转换为可哈希形式
unique = set(tuple(x) if isinstance(x, list) else x for x in data)
# 结果: {1, 2, 5, (3, 4)}

场景2:缓存/记忆化

python

python 复制代码
from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
    """缓存需要参数可哈希"""
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# ✅ 参数 int 可哈希,可以缓存
fibonacci(10)

# ❌ 如果参数是列表,不能使用 lru_cache

场景3:字典统计频率

python

python 复制代码
# ✅ 使用可哈希类型作为键
freq = {}
words = ["apple", "banana", "apple"]
for word in words:
    freq[word] = freq.get(word, 0) + 1  # word 是 str,可哈希

# ❌ 不能统计列表的频率
data = [[1,2], [1,2], [3,4]]
freq = {}
for item in data:
    freq[item] = freq.get(item, 0) + 1  # TypeError

八、如何让自定义类可哈希?

python

python 复制代码
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    # 实现 __hash__ 方法
    def __hash__(self):
        return hash((self.x, self.y))
    
    # 实现 __eq__ 方法
    def __eq__(self, other):
        if not isinstance(other, Point):
            return False
        return self.x == other.x and self.y == other.y
    
    # 使其不可变(可选)
    def __setattr__(self, name, value):
        if hasattr(self, name):
            raise AttributeError(f"Cannot modify {name}")
        super().__setattr__(name, value)

# 现在 Point 对象可以作为字典键
p1 = Point(1, 2)
p2 = Point(1, 2)
d = {p1: "A点"}
print(d[p2])  # "A点",因为 p1 == p2

九、快速总结表

特性 可哈希 不可哈希
有哈希值
可比较相等 可能可以
不可变 通常可变
可作字典键
可作集合元素
典型代表 int, str, tuple list, dict, set

记忆口诀 :可变不可哈希,不可变可哈希。字典的键和集合的元素,都必须是可哈希。

相关推荐
21439652 小时前
Redis如何解决哨兵通知延迟问题_优化客户端连接池动态刷新拓扑的订阅监听机制
jvm·数据库·python
川石课堂软件测试2 小时前
requests接口自动化测试
数据库·python·功能测试·测试工具·单元测试·grafana·prometheus
2401_871696522 小时前
HTML5中Canvas局部刷新区域重绘的算法优化
jvm·数据库·python
2301_777599372 小时前
CSS如何制作卡片翻转效果_利用backface-visibility与动画
jvm·数据库·python
解救女汉子2 小时前
Python 中正确声明、重新赋值并安全使用 None 初始化变量的完整指南
jvm·数据库·python
梦想的初衷~2 小时前
Biome-BGC 模型全攻略:气象数据处理、参数调优、敏感性归因分析全覆盖
python·全球变化·生态系统模拟·碳氮水循环·遥感生态·陆面过程·区域碳汇
a9511416422 小时前
CSS 悬停箭头闪烁偏移问题的根源与稳定解决方案
jvm·数据库·python
free_732 小时前
OpenClaw×AI隐私安全舱——ClawVault:重新定义企业级智能数据防线
人工智能·python·安全
jr-create(•̀⌄•́)2 小时前
Deep Learning入门---基本概念
人工智能·python·深度学习