本文系统总结了Python中的数据类型分类及特性。
主要内容包括:
- 数据类型分类:基本类型(int/float/str等)、序列类型(list/tuple/range)、映射类型(dict)、集合类型(set/frozenset)和二进制序列类型(bytes/bytearray);
- 类型特性对比:可变性(list/dict可变,tuple/str不可变)、有序性(list有序,set无序)和可哈希性(可哈希类型可作为字典键);
- 可哈希性详解:定义了可哈希对象的条件(不可变、有哈希值、可比较相等),列举了常见可哈希与不可哈希类型,并说明了可哈希性的实际应用场景;
- 类型转换与判断方法。
全文通过对比表格和示例代码,清晰展示了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
二、可哈希类型的特征
一个对象是可哈希的,需要满足以下条件:
-
✅ 有哈希值 - 实现
__hash__()方法 -
✅ 可比较相等 - 实现
__eq__()方法 -
✅ 不可变 - 创建后内容不能改变
三、常见可哈希与不可哈希类型
| 类型 | 可哈希? | 原因 |
|---|---|---|
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 |
记忆口诀 :可变不可哈希,不可变可哈希。字典的键和集合的元素,都必须是可哈希。