当前位置: 首页 > news >正文

Python小酷库系列:Box,更为完善的dict属性化访问扩展库

更为完善的dict属性化访问扩展库

    • 基本使用
      • 0、安装
      • 1、创建一个 box 对象
      • 2、嵌套结构支持
      • 3、更新与递归合并
      • 4、访问不存在的键
      • 5、保护关键字(如 keys, items)
      • 6、支持 JSON/YAML 读写
    • 进阶功能
      • 1、BoxList
      • 2、FrozenBox
    • 实现原理
      • 1、实现原理
      • 2、性能与应用场景

在 Python小酷库系列:Munch,用对象的访问方式访问dict 一节我们介绍了Munch,它可以让你用属性方式访问dict中的数据。Munch支持嵌套结构、深度拷贝等复杂dict结构,可用于大多数场景。本节我们介绍另一个具有相似功能的Python dict扩展库——Box,它允许你使用点符号(.)来访问字典中的数据,支持嵌套结构、自定义默认行为、YAML/JSON 支持等高级特性。相比同类型的库,它更强大、更灵活,也有更清晰的行为控制。

基本使用

0、安装

pip install python-box
# 若需 YAML 支持:
pip install python-box[all]

1、创建一个 box 对象

from box import Box
data = Box({"user": {"name": "Alice","age": 30}
})
print(data.user.name)     # Alice
print(data["user"]["age"])  # 30

2、嵌套结构支持

nested = Box({'user': {'name': 'Bob','profile': {'email': 'bob@example.com'}}
})print(nested.user.profile.email)  # bob@example.com

Box 会自动将嵌套的 dict 转换成 Box 实例。

3、更新与递归合并

Box 可以通过update()方法将另一个Box示例或字典合并进当前实例:

from box import Box   
user = Box({  'name': 'Bob',  'age': 30,  'profile': {  'email': 'bob@example.com'  }  
})  
user.update({'profile': {'city': 'beijing'}})
print(user)
# {'name': 'Bob', 'age': 30, 'profile': {'city': 'beijing'}}

Box还提供了merge_update()方法,它支持递归合并。

from box import Box   
user = Box({  'name': 'Bob',  'age': 30,  'profile': {  'email': 'bob@example.com'  }  
})  
user.merge_update({'profile': {'city': 'beijing'}})
print(user)
# {'name': 'Bob', 'age': 30, 'profile': {'email': 'bob@example.com', 'city': 'beijing'}}

4、访问不存在的键

Box可以通过开启默认值(default_box=True)来避免访问不存在的键时报错:

b = Box(default_box=True)
print(b.anything.really.deep.here)  # 自动生成嵌套结构
# {}

5、保护关键字(如 keys, items)

Box 使用特殊机制保护了 dict 方法,不会覆盖:

b = Box({"keys": "mykeys"})
print(b["keys"])    # 正确
print(b.keys())     # 仍然是 dict.keys 方法

6、支持 JSON/YAML 读写

from box import Box
import jsonb = Box({"name": "Alice", "age": 30})# JSON
json_str = b.to_json()
print(json_str)# YAML(需安装 pyyaml)
# b.to_yaml(filename='config.yaml')

进阶功能

1、BoxList

如果你将一个列表封装进 Box,它会变成 BoxList:

b = Box({'users': [{'name': 'Tom'}, {'name': 'Jerry'}]})
print(b.users[0].name)  # Tom

2、FrozenBox

不可变版本,尝试修改将报错:

from box import Box, FrozenBox
f = FrozenBox({'a': 1})
f.a = 2  # 抛出错误

实现原理

1、实现原理

Box 就是一个递归封装的 dict,它用属性访问模拟对象风格的调用方式,同时保持 dict 的所有兼容性。其核心是对魔法方法的重载(如 __getattr___boxify)。

__getattr__ 实现点号访问

def __getattr__(self, item):try:return self[item]except KeyError:if self._default_box:self[item] = self.__class__(default_box=True)return self[item]raise AttributeError(...)

这时,当你执行 box.name 时:

  • 先尝试从字典中获取值
  • 如果 default_box=True,则自动创建嵌套 Box
  • 否则抛出 AttributeError

__setattr____delattr__

def __setattr__(self, key, value):if key.startswith('_') or key in self.__class__.__dict__:super().__setattr__(key, value)else:self[key] = value

这些方法重定向属性设置到 dict,这样做的好处:

  • 设置 box.name = “Alice” 等价于 box[“name”] = “Alice”
  • 保留 _box_config 等私有字段的属性行为不被覆盖

递归封装嵌套结构(关键)

def _boxify(self, value):if isinstance(value, dict):return self.__class__(value, **self._box_config)elif isinstance(value, list):return [self._boxify(item) for item in value]return value

初始化或赋值时会使用 _boxify 自动转换嵌套结构:

  • 嵌套字典 → 转为 Box
  • 嵌套列表 → 遍历元素递归处理

支持原生 dict 方法:保护关键字

if attr in dir(dict):return object.__getattribute__(self, attr)

Box 会区分是否在调用 box.keys() 方法,还是访问键名为 “keys” 的字段,这种机制避免了 .keys, .items 被用户数据覆盖的问题。

2、性能与应用场景

Box在属性访问上需要多次调用函数,在性能上相较于原生dict会有明显的开销,它并不适合对性能要求极高的实时服务或频繁大规模数据计算/遍历的算法,而更适合用于 增强可读性减少样板代码管理复杂配置

http://www.xdnf.cn/news/326089.html

相关文章:

  • 技术视界 | 青龙机器人训练地形详解(一):如何创建一个地形
  • HTB - Eureka记录
  • 数智管理学(八)
  • 《饶议科学》阅读笔记
  • 【Lanqiao】数位翻转
  • 2021年下半年试题四:论微服务架构及其应用
  • SQL Server 中的 GO 及其与其他数据库的对比
  • Spark-Core(双Value类型)
  • C++对象注册系统(1)实现原理
  • 应用 | AI 自动化某讯会议转录与摘要生成系统
  • Android开发-视图基础
  • Facebook的元宇宙新次元:社交互动如何改变?
  • 2021年CVPR文章【Polygonal Building Segmentation by Frame Field Learning】环境搭建
  • 《Python星球日记》 第47天:聚类与KMeans
  • Kotlin zip 函数的作用和使用场景
  • 镜像和容器的管理
  • Qwen2.5模型结构
  • QT编程练习20250507
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】7.1 主流可视化工具对比(Tableau/Matplotlib/Python库)
  • FreeCAD傻瓜教程-涡轮蜗杆的快速绘制FCGear工作台的使用方法
  • 算法专题四:前缀和
  • 【北京迅为】iTOP-4412精英版使用手册-第八章 Android 4.4系统编译
  • neo4j多跳查询,未只获取到收尾两个节点,待继续
  • 智能运维实战|数据库卡慢处置的一次关键事件
  • 尚硅谷-硅谷甄选项目记录
  • Facebook隐私设置详解:如何保护你的个人信息
  • 【漫话机器学习系列】245.权重衰减(Weight Decay)
  • SR触发器为什么能够消抖
  • Vue 项目中长按保存图片功能实现指南
  • AI大模型基础设施:NVIDIA GPU和AMD MI300系列的区别