整体说明
- EasyDict 是一个轻量级的 Python 库,旨在简化字典操作,它允许用户像访问对象属性一样访问字典的键值对,从而提高代码的可读性和简洁性
- EasyDict 通过重写字典的几个关键方法,如
__getattr__和__setattr__等,实现了将字典键转换为对象属性的功能 - EasyDict 不仅支持顶级字典的属性访问方式,还能递归应用于内嵌的字典,使得处理多层次数据结构变得简单易行
- EasyDict 实例仍然遵循标准字典的所有操作,保证了灵活性
安装 EasyDict
- 可以使用pip进行安装,命令如下:
1
pip install easydict
使用示例
简单使用示例:
1
2
3
4
5
6
7
8
9from easydict import EasyDict as edict
# 创建一个EasyDict对象
data = edict({'name': 'John', 'age': 30, 'job': 'Engineer'})
# 访问字典元素
print(data.age)
print(data.job)
# 添加新的键值对
data.gender = 'Male'
print(data.gender)嵌套字典的访问:
1
2
3
4
5
6
7
8my_dict = edict({
'level1': edict({
'level2': edict({
'key': 'value'
})
})
})
print(my_dict.level1.level2.key)动态设置属性:
1
2
3my_dict = edict()
my_dict.key1 = 'value1'
print(my_dict.key1)常见的字典操作:
1
2
3
4
5
6
7my_dict = edict({'key1': 'value1'})
# 更新字典
my_dict.update({'key2': 'value2'})
print(my_dict.key2)
# 删除一个键值对
my_dict.pop('key1')
print(my_dict.key1) # 会抛出AttributeError,因为'key1'不再存在获取默认值:
1
2
3my_dict = edict({'name': 'Alice'})
value = my_dict.get('nonexistent_key', 'default_value')
print(value)
EasyDict 和 namedtuple 对比
- EasyDict 和
namedtuple都是 Python 中用于简化数据访问的工具 - TDRL:
namedtuple是”先定义类,再用类创建实例”;EasyDict 是”直接用通用类创建实例,动态定义结构”namedtuple需要先定义特定结构的类(如Person),再创建该类的实例,适合固定结构的数据- EasyDict 直接使用通用的
EasyDict类创建实例,实例的字段结构可以动态变化,适合灵活的数据场景
- TDRL:若需 固定结构、不可变数据 ,追求性能和内存效率,用
namedtuple;若需 动态结构、灵活修改 ,优先便捷性,用 EasyDict
本质与继承关系
namedtuple是tuple的子类,属于不可变(immutable)数据结构- 一旦创建,其字段值无法修改,类似元组的特性
namedtuple定义时需要指定固定的字段名,结构是静态的,不能动态添加新字段- EasyDict 是
dict的子类,属于可变(mutable)数据结构- 创建后可以随时修改字段值,也能动态添加/删除新字段,保留了字典的灵活性
数据访问方式
- 两者都支持 属性式访问(如
obj.field)和 键值访问(如obj['field']),但底层实现不同:namedtuple本质是元组,字段值存储在固定位置,访问速度更快- EasyDict 本质是字典,通过重写
__getattr__实现属性访问,性能略低于namedtuple
可变性
namedtuple不可变:创建后无法修改字段值,也不能添加新字段,类似常量集合,示例如下:1
2
3
4from collections import namedtuple
Person = namedtuple('Person', ['name', 'age'])
p = Person('Alice', 30)
p.age = 31 # 报错:'Person' object does not support item assignmentEasyDict 可变:支持修改现有字段、添加新字段、删除字段等操作,示例如下:
1
2
3
4
5from easydict import EasyDict as edict
p = edict(name='Alice', age=30)
p.age = 31 # 允许修改
p.gender = 'Female' # 允许添加新字段
del p.age # 允许删除字段
定义类情况
namedtuple显式定义了一个新的类(如Person),这个类继承自tuple,并且在定义时就固定了字段结构,例如:1
2
3
4from collections import namedtuple
# 这里显式创建了一个名为 Person 的类
Person = namedtuple('Person', ['name', 'age'])
print(type(Person)) # 输出:<class 'type'>,说明是一个类- 后续使用时,
Person()是创建该类的实例,每个实例都严格遵循预定义的字段结构
- 后续使用时,
EasyDict 没有要求你显式定义新的类(如
Person),但它本身是一个通用的EasyDict类,所有实例都属于这个类,例如:1
2
3
4from easydict import EasyDict as edict
# 直接创建 EasyDict 类的实例,无需预先定义结构
p = edict(name='Alice', age=30)
print(type(p)) # 输出:<class 'easydict.EasyDict'>- 你将
p视为一个”动态对象”,它属于EasyDict类,但其字段可以灵活添加/修改,不需要提前定义特定的类(如Person)
- 你将
适用场景
namedtuple适合存储 固定结构、不可变的数据(如配置项、记录、坐标等),强调数据的稳定性和内存效率- 例如:表示点坐标
Point(x=1, y=2)、数据库查询结果等
- 例如:表示点坐标
- EasyDict 适合处理 动态结构、需要灵活修改的数据(如嵌套配置、JSON 数据解析等),强调操作的便捷性
- 例如:解析 API 返回的 JSON 数据(可动态添加/修改字段)、多层级的配置文件等
其他差异
- 内存占用 :
namedtuple比 EasyDict 更轻量,内存占用更少 - 序列化 :两者都支持序列化,但
namedtuple可直接通过_asdict()转换为普通字典,EasyDict 本身就是字典,可直接序列化 - 类型提示 :
namedtuple在定义时已明确字段,类型提示更友好;EasyDict 动态字段较多,类型提示较弱