Python小酷库系列:Munch,用对象的访问方式访问dict

Munch,用对象的访问方式访问dict

    • 基本使用
      • 1、创建一个 Munch 对象
      • 2、使用字典初始化
      • 3、访问不存在的字段
      • 4、嵌套结构支持
      • 5、合并操作
      • 6、应用场景说明
    • 进阶功能
      • 1、嵌套写入:创建不存在的子对象
      • 2、序列化(转回 dict)
      • 3、深度拷贝结构
      • 4、与 JSON 配合:动态数据结构绑定
      • 5、与 Pydantic/配置类组合使用(读取动态配置)
    • 实现原理
      • 1、继承自 dict
      • 2、 重写了 `__getattr__` 和 `__setattr__` 方法
      • 3、`__delattr__` 支持删除属性
      • 4、递归嵌套(来自 DefaultMunch.fromDict())
    • 编写一个更高性能的Munch

Munch 是 Python 中一个小巧实用的库,它将字典(dict)扩展为支持“点操作”的对象访问方式,即:

data = Munch({"name":"Alice", "age":18})
print(data.name)   # 而不是 data["name"]

它特别适用于配置读取、JSON 响应处理、动态数据访问等场景。

基本使用

1、创建一个 Munch 对象

from munch import Munchm = Munch()
m.name = "Alice"
m.age = 30print(m['name'])   # Alice
print(m.name)      # Alice

2、使用字典初始化

user = Munch({'id': 1, 'username': 'bob'})
print(user.username)  # bob

3、访问不存在的字段

当你访问一个 Munch 对象中不存在的键(属性) 时,Munch将抛出AttributeError。我们可以通过以下几种方式安全地访问Munch 对象的键(属性):
使用 .get() 方法(dict 风格)

print(m.get('age'))           # 输出 None
print(m.get('age', 0))        # 输出默认值 0

使用 in 判断键是否存在

if 'age' in m:print(m.age)

使用 DefaultMunch 自动返回默认值(推荐)

from munch import DefaultMunchm = DefaultMunch(None, {"name": "Alice"})print(m.name)   # Alice
print(m.age)    # None(不会报错)

4、嵌套结构支持

from munch import DefaultMunch
nested = DefaultMunch.fromDict({"user": {"id": 10,"profile": {"email": "user@example.com"}}
})
print(nested.user.profile.email)  # user@example.com

5、合并操作

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

from munch import Muncha = Munch(foo=1, nested=Munch(x=1, y=2))
b = {"nested": {"y": 20, "z": 30}}a.update(b)
print(a)
# 结果为Munch({'foo': 1, 'nested': {'y': 20, 'z': 30}})

update() 是 浅合并(shallow merge),如果需要递归合并,可以这样手动实现:

def recursive_update(target, source):for key, value in source.items():if key in target and isinstance(target[key], dict) and isinstance(value, dict):recursive_update(target[key], value)else:target[key] = valuea = Munch(foo=1, nested=Munch(x=1, y=2))
b = {"nested": {"y": 20, "z": 30}}recursive_update(a, b)
print(a)
# 输出Munch({'foo': 1, 'nested': Munch({'x': 1, 'y': 20, 'z': 30})})

6、应用场景说明

Munch 的性能总体上略低于原生 dict,这是因为它在属性访问时多了一层 Python 层的函数调用(比如 getattrsetattr 等),但它仍然足够轻量,适合大多数非性能瓶颈场景。

Munch适合用于:

  • 配置读取(如 config.json)
  • CPU 密集或低延迟要求的核心路径
  • 结构化 JSON 响应封装

不建议将Munch用于:

  • 类型严格检查的项目(除非手动封装)
  • 数据探索、Jupyter Notebook 脚本开发
  • 内存/性能受限的环境

进阶功能

1、嵌套写入:创建不存在的子对象

nested = DefaultMunch(dict)
nested.user.info.email = "a@example.com"
print(nested)  # {'user': {'info': {'email': 'a@example.com'}}}

2、序列化(转回 dict)

m = Munch(name="Alice", age=30)
d = m.toDict()
print(type(d))  # dict

3、深度拷贝结构

import copy
m = Munch(a=1, b={"x": 10})
m_copy = copy.deepcopy(m)

4、与 JSON 配合:动态数据结构绑定

import json
from munch import Munchjson_str = '{"user": {"id": 42, "roles": ["admin", "editor"]}}'
m = Munch(json.loads(json_str))
print(m.user.roles)  # ['admin', 'editor']

5、与 Pydantic/配置类组合使用(读取动态配置)

import yaml
from munch import Munchwith open("config.yaml") as f:config_dict = yaml.safe_load(f)config = Munch(config_dict)
print(config.database.host)

实现原理

Munch 的原理很简单:它是在 Python 内置的 dict 类的基础上,通过重写属性访问相关方法,实现了 “点操作”访问字典内容 的能力。

1、继承自 dict

class Munch(dict):...

因此,Munch本质上还是一个字典。

2、 重写了 __getattr____setattr__ 方法

这些方法控制了对象属性的读取和设置:

def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError(f"'Munch' object has no attribute {key}")def __setattr__(self, key, value):self[key] = value

3、__delattr__ 支持删除属性

def __delattr__(self, key):try:del self[key]except KeyError:raise AttributeError(f"'Munch' object has no attribute {key}")

这保证了 del m.attr 与 del m[‘attr’] 效果一致。

4、递归嵌套(来自 DefaultMunch.fromDict())

这个功能将嵌套的字典也转换为 Munch:

@classmethod
def fromDict(cls, d):return cls({k: cls.fromDict(v) if isinstance(v, dict) else v for k, v in d.items()})

编写一个更高性能的Munch

有了Munch实现原理的理解,接下来我们实现一个轻量级、性能更高的 “点操作字典” 替代方案:DotDict。它模仿了 Munch 的基本行为,但去除了递归转换、类型检查等附加功能,以提高性能。
dot_dict.pyDotDict完整源码

class DotDict(dict):"""更快的支持点操作的 dict,不做嵌套转换。"""def __getattr__(self, key):try:return self[key]except KeyError as e:raise AttributeError(key) from edef __setattr__(self, key, value):self[key] = valuedef __delattr__(self, key):try:del self[key]except KeyError as e:raise AttributeError(key) from e

test_dot_dict.pyDotDict测试示例

data = DotDict(name="Alice", age=30)print(data.name)     # 点操作访问
print(data['age'])   # 仍可用原生字典方式data.city = "Beijing"
print(data['city'])  # 北京

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/80411.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对称加密以及非对称加密

对称加密和非对称加密是两种不同的加密方式,它们在加密原理、密钥管理、安全性和性能等方面存在区别,以下是具体分析: 加密原理 对称加密:通信双方使用同一把密钥进行加密和解密。就像两个人共用一把钥匙,用这把钥匙锁…

[JAVAEE]HTTP协议(2.0)

响应报文格式 响应报文格式由首行,响应头(header),空行,正文(body) 组成 响应报文首行包括 1.版本号 如HTTP/1.1 2.状态码(如200) 描述了请求的结果 3.状态码描述(如OK) 首行——状态码…

Spring Boot 之MCP Server开发全介绍

Spring AI 的 MCP(模型上下文协议,Model Context Protocol)服务器启动器为在 Spring Boot 应用程序中设置 MCP 服务器提供了自动配置功能。它使得 MCP 服务器功能能够与 Spring Boot 的自动配置系统实现无缝集成。 MCP 服务器启动器具备以下特性: MCP 服务器组件的自动配置…

YOLOv8 对象检测任务的标注、训练和部署过程

YOLOv8 对象检测任务的标注、训练和部署过程 在计算机视觉领域,对象检测是一项基础且重要的任务,YOLOv8 作为当前先进的实时对象检测模型,以其高效性和准确性受到广泛关注。从数据准备到最终模型部署,整个流程包含多个关键环节&a…

电池热管理CFD解决方案,为新能源汽车筑安全防线

在全球能源结构加速转型的大背景下,新能源汽车产业异军突起,成为可持续发展的重要驱动力。而作为新能源汽车 “心脏” 的电池系统,其热管理技术的优劣,直接决定了车辆的安全性、续航里程和使用寿命。电池在充放电过程中会产生大量…

Redis 数据类型:掌握 NoSQL 的基石

Redis (Remote Dictionary Server) 是一种开源的、内存中的数据结构存储系统,通常用作数据库、缓存和消息代理。 它的高性能和丰富的数据类型使其成为现代应用程序开发中不可或缺的一部分。 本文将深入探讨 Redis 的核心数据类型,帮助你更好地理解和利用…

MLX-Audio:高效音频合成的新时代利器

MLX-Audio:高效音频合成的新时代利器 现代社会的快节奏生活中,对语音技术的需求越来越高。无论是个性化语音助手,还是内容创作者所需的高效音频生成工具,语音技术都发挥着不可或缺的作用。今天,我们将介绍一个创新的开…

Kafka单机版安装部署

目录 1.1、概述1.2、系统环境1.3、ZooKeeper的作用1.4、部署流程1.4.1、下载安装包1.4.2、解压文件1.4.3、创建日志目录1.4.4、配置Kafka1.4.5、启动Kafka服务1.4.6、启动成功验证 1.5、创建Topic测试1.6、消息生产与消费测试1.6.1、启动生产者1.6.2、启动消费者 1.1、概述 Kaf…

【C++设计模式之Observer观察者模式】

Observer观察者模式 模式定义动机(Motivation)结构(Structure)应用场景一(气象站)实现步骤1.定义观察者接口2.定义被观察者(主题)接口3.实现具体被观察者对象(气象站)4.实现具体观察者(例如:显示屏)5.main.cpp中使用示例6.输出结果7. 关键点 …

资产月报怎么填?资产月报填报指南

资产月报是企业对固定资产进行定期检查和管理的重要工具,它能够帮助管理者了解资产的使用情况、维护状况和财务状况,从而为资产的优化配置和决策提供依据。填写资产月报时,除了填报内容外,还需要注意格式的规范性和数据的准确性。…

UG471 之 SelectIO 逻辑资源

背景 《ug471》介绍了Xilinx 7 系列 SelectIO 的输入/输出特性及逻辑资源的相关内容。 第 1 章《SelectIO Resources》介绍了输出驱动器和输入接收器的电气特性,并通过大量实例解析了各类标准接口的实现。 第 2 章《SelectIO Logic Resources》介绍了输入输出数据…

C++ 内存泄漏相关

ASAN 参考链接 https://blog.csdn.net/wonengguwozai/article/details/129593186https://www.cnblogs.com/greatsql/p/16256926.htmlhttps://zhuanlan.zhihu.com/p/700505587小demo // leak.c #include <stdio.h> #include <stdlib.h> #include <string.h>…

计算人声录音后电平的大小(dB SPL->dBFS)

计算人声录音后电平的大小 这里笔记记录一下&#xff0c;怎么计算已知大小的声音&#xff0c;经过麦克风、声卡录制后软件内录得的音量电平值。&#xff08;文章最后将计算过程整理为Python代码&#xff0c;方便复用&#xff09; 假设用正常说话的声音大小65dB&#xff08;SP…

【MySQL数据库】C/C++连接数据库

MySQL要想在C/C下使用&#xff0c;就必须要有 MySQL 提供的头文件和相关的库。 在Ubuntu系统上&#xff0c;使用 apt install mysql-server 安装MySQL服务器后&#xff0c;仅安装了MySQL数据库服务本身&#xff0c;并没有安装MySQL开发所需的库和头文件。因此&#xff0c;在尝试…

Kubernetes调度策略深度解析:NodeSelector与NodeAffinity的正确打开方式

在Kubernetes集群管理中&#xff0c;如何精准控制Pod的落点&#xff1f;本文将深入解析两大核心调度策略的差异&#xff0c;并通过生产案例教你做出正确选择。 一、基础概念快速理解 1.1 NodeSelector&#xff08;节点选择器&#xff09; 核心机制&#xff1a;通过标签硬匹配…

Golang的linux运行环境的安装与配置

很多新手在学go时&#xff0c;linux下的配置环境一头雾水&#xff0c;总结下&#xff0c;可供参考&#xff01; --------------------------------------Golang的运行环境的安装与配置-------------------------------------- 将压缩包放在/home/tools/下 解压 tar -zxvf g…

自定义实现elementui的锚点

背景 前不久有个需求&#xff0c;上半部分是el-step步骤条&#xff0c;下半部分是一些文字说明&#xff0c;需要实现点击步骤条中某个步骤自定义定位到对应部分的文字说明&#xff0c;同时滚动内容区域的时候还要自动选中对应区域的步骤。element-ui-plus的有锚点这个组件&…

Oracle Fusion常用表

模块表名表描述字段说明sodoo_headers_all销售订单头表sodoo_lines_all销售订单行表sodoo_fulfill_lines_all销售订单明细行表popo_headers_all采购订单头表popo_lines_all采购订单行表popo_line_locations_all采购订单分配表popo_distributions_all采购订单发运表invEGP_SYSTE…

面试常问系列(一)-神经网络参数初始化-之-softmax

背景 本文内容还是对之前关于面试题transformer的一个延伸&#xff0c;详细讲解一下softmax 面试常问系列(二)-神经网络参数初始化之自注意力机制-CSDN博客 Softmax函数的梯度特性与输入值的幅度密切相关&#xff0c;这是Transformer中自注意力机制需要缩放点积结果的关键原…

5.9-selcct_poll_epoll 和 reactor 的模拟实现

5.9-select_poll_epoll 本文演示 select 等 io 多路复用函数的应用方法&#xff0c;函数具体介绍可以参考我过去写的博客。 先绑定监听的文件描述符 int sockfd socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(struc…