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

Python 魔术方法深度解析:__getattr__ 与 __getattribute__

一、核心概念与差异解析

1. __getattr__ 的定位与特性

触发时机
当访问对象中 ​**不存在的属性** 时自动触发,是 Python 属性访问链中的最后一道防线。

核心能力

  • 动态生成缺失属性
  • 实现优雅的错误处理
  • 构建链式调用接口(如 REST API 客户端)
class DynamicAPI:def __getattr__(self, name):print(f"拦截未定义属性:{name}")return lambda: f"动态生成 {name} 方法"api = DynamicAPI()
print(api.get_users())  # 输出:拦截未定义属性 → 动态生成 get_users 方法

2. getattribute 的全局拦截

触发时机
所有属性访问​(包括已存在的属性)都会触发此方法。

危险与机遇

  • 需通过 super().getattribute() 访问真实属性
  • 可构建全局属性访问日志系统
  • 不当使用会导致无限递归(如直接访问 self.name,这里需要特别注意)
class AuditLogger:def __getattribute__(self, name):print(f"审计日志 → 访问属性:{name}")return super().__getattribute__(name)obj = AuditLogger()
obj.value = 10
print(obj.value)  # 输出:审计日志 → 访问属性 value → 10

二、实战场景与代码示例

场景 1:动态 REST API 客户端(getattr

class APIClient:def __init__(self, base_url):self.base_url = base_urlself._path = []def __getattr__(self, endpoint):self._path.append(endpoint)return self  # 支持链式调用def __call__(self, *args):url = f"{self.base_url}/{'/'.join(self._path)}/{'/'.join(map(str, args))}"self._path = []  # 重置路径return f"请求 {url}"api = APIClient("https://api.example.com")
print(api.v1.users(123))
# 输出:请求 https://api.example.com/v1/users/123

实现要点

  • 通过链式调用构建 URL 路径
  • 使用 **__call__** 处理路径参数
  • 每次调用后清空路径缓存

场景 2:属性访问日志系统(getattribute

class AccessMonitor:def __init__(self):self._data = {"secret": "TOP_SECRET"}def __getattribute__(self, name):if name == "_data":  # 避免递归return super().__getattribute__(name)print(f"[监控] 访问属性 {name}")if name in super().__getattribute__("_data"):return self._data[name]raise AttributeError(f"属性 {name} 不存在")obj = AccessMonitor()
print(obj.secret)  # 输出:[监控] 访问属性 secret → TOP_SECRET

安全实践

  • 用 super() 访问父类方法
  • 单独处理特殊属性(如 _data)
  • 显式抛出 AttributeError 保持行为一致性

三、关键陷阱与避坑指南

陷阱 1:递归地狱

错误示例

class RecursionDemo:def __getattribute__(self, name):return self.__dict__[name]  # 触发无限递归!
正确方案:pythondef __getattribute__(self, name):return super().__getattribute__(name)  # 通过父类访问

陷阱 2:属性遮蔽

特殊场景
当类中已存在同名方法时,**__getattr__** 不会被触发:

class ShadowDemo:def existing_method(self):passdef __getattr__(self, name):print("这个方法永远不会被触发!")obj = ShadowDemo()
obj.existing_method()  # 直接调用已存在方法

四、最佳实践与设计原则

  1. 职责分离原则
  • **__getattr__**:处理缺失属性的动态生成
  • **__getattribute__**:实现全局访问控制或审计
  1. ​防御性编程
  • **__getattribute__** 中优先处理 __dict__ 访问
  • 使用 hasattr() 检查属性存在性前先考虑触发逻辑
  1. 性能优化
  • 避免在 **__getattribute__** 中执行复杂操作
  • 对高频访问属性使用 @property 装饰器

五、扩展应用:实现动态配置系统

class EnvConfig:def __getattr__(self, name):value = os.getenv(name.upper())if not value:raise AttributeError(f"环境变量 {name.upper()} 未配置")return valueconfig = EnvConfig()
print(config.db_host)  # 自动读取 DB_HOST 环境变量

设计亮点

  • 将属性名转换为大写环境变量名
  • 实现配置项的按需加载
  • 保持与传统配置类的接口兼容性

通过掌握这两个魔术方法,开发者可以实现从简单的动态属性生成到复杂的元编程框架。建议在实际项目中优先使用 **__getattr__**,仅在需要全局控制时谨慎使用 **__getattribute__**

相关文章:

Python 魔术方法深度解析:__getattr__ 与 __getattribute__

一、核心概念与差异解析 1. __getattr__ 的定位与特性 触发时机: 当访问对象中 ​**不存在的属性** 时自动触发,是 Python 属性访问链中的最后一道防线。 核心能力: 动态生成缺失属性实现优雅的错误处理构建链式调用接口(如 R…...

【机器学习】机器学习工程实战-第2章 项目开始前

上一章:第1章 概述 文章目录 2.1 机器学习项目的优先级排序2.1.1 机器学习的影响2.1.2 机器学习的成本 2.2 估计机器学习项目的复杂度2.2.1 未知因素2.2.2 简化问题2.2.3 非线性进展 2.3 确定机器学习项目的目标2.3.1 模型能做什么2.3.2 成功模型的属性 2.4 构建机…...

【UI设计】一些好用的免费图标素材网站

阿里巴巴矢量图标库https://www.iconfont.cn/国内最大的矢量图标库之一,拥有 800 万 图标资源。特色功能包括团队协作、多端适配、定制化编辑等,适合企业级项目、电商设计、中文产品开发等场景。IconParkhttps://iconpark.oceanengine.com/home字节跳动…...

Visual Studio(VS)的 Release 配置中生成程序数据库(PDB)文件

最近工作中的一个测试工具在测试多台设备上使用过程中闪退,存了dump,但因为是release版本,没有pdb,无法根据dump定位代码哪块出了问题,很苦恼,查了下怎么加pdb生成,记录一下。以下是具体的设置步…...

ubuntu 解挂载时提示 “umount: /home/xx/Applications/yy: target is busy.”

问题如题所示,我挂载一个squanfs文件系统到指定目录,当我使用完后,准备解挂载时,提示umount: /home/xx/Applications/yy: target is busy.,具体的如图所示, 这种提示通常是表明这个路径的内容正在被某些进…...

一条不太简单的TEX学习之路

目录 rule raisebox \includegraphics newenviro 、\vspace \stretch \setlength 解释: 总结: 、\linespread newcommand \par 小四 \small simple 、mutiput画网格 解释: 图案解释: xetex pdelatex etc index 报…...

Matplotlib完全指南:数据可视化从入门到实战

目录 引言 一、环境配置与基础概念 1.1 安装Matplotlib 1.2 导入惯例 1.3 两种绘图模式 二、基础图形绘制 2.1 折线图(Line Plot) 2.2 柱状图(Bar Chart) 三、高级图表类型 3.1 散点图(Scatter Plot&#xff…...

在大数据开发中ETL是指什么?

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在数字经济时代,数据已成为企业最核心的资产。然而,分散在业务系统、日志文件…...

OAuth 2.0认证

文章目录 1. 引言1.1 系列文章说明1.2 OAuth 2.0 的起源与演变1.3 应用场景概览 2. OAuth 2.0 核心概念2.1 角色划分2.2 核心术语解析 3. 四种授权模式详解3.1 授权码模式(Authorization Code Grant)3.1.1 完整流程解析3.1.2 PKCE 扩展(防止授…...

【Linux 下的 bash 无法正常解析, Windows 的 CRLF 换行符问题导致的】

文章目录 报错原因:解决办法:方法一:用 dos2unix 修复方法二:手动转换换行符方法三:VSCode 或其他编辑器手动改 总结 这个错误很常见,原因是你的 wait_for_gpu.sh 脚本 文件格式不对,具体来说…...

Kubernetes的Replica Set和ReplicaController有什么区别

ReplicaSet 和 ReplicationController 是 Kubernetes 中用于管理应用程序副本的两种资源,它们有类似的功能,但 ReplicaSet 是 ReplicationController 的增强版本。 以下是它们的主要区别: 1. 功能的演进 ReplicationController 是 Kubernete…...

WSL 导入完整系统包教程

作者: DWDROME 配置环境: OS: Ubuntu 20.04.6 LTS on Windows 11 x86_64Kernel: 5.15.167.4-microsoft-standard-WSL2ros-noetic 🧭WSL 导入完整系统包教程 ✅ 一、准备导出文件 假设你已有一个 .tar 的完整系统包(如从 WSL 或 L…...

[Lc_2 二叉树dfs] 布尔二叉树的值 | 根节点到叶节点数字之和 | 二叉树剪枝

目录 1.计算布尔二叉树的值 题解 2.求根节点到叶节点数字之和 3. 二叉树剪枝 题解 1.计算布尔二叉树的值 链接:2331. 计算布尔二叉树的值 给你一棵 完整二叉树 的根,这棵树有以下特征: 叶子节点 要么值为 0 要么值为 1 ,其…...

SOFABoot-07-版本查看

前言 大家好,我是老马。 sofastack 其实出来很久了,第一次应该是在 2022 年左右开始关注,但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概览 SOFABoot-01-蚂蚁金服开源的 s…...

蓝桥杯 之 第27场月赛总结

文章目录 习题1.抓猪拿国一2.蓝桥字符3.蓝桥大使4.拳头对决 习题 比赛地址 1.抓猪拿国一 十分简单的签到题 print(sum(list(range(17))))2.蓝桥字符 常见的字符匹配的问题,是一个二维dp的问题,转化为对应的动态规划求解 力扣的相似题目 可以关注灵神…...

第十六章:Specialization and Overloading_《C++ Templates》notes

Specialization and Overloading 一、模板特化与重载的核心概念二、代码实战与测试用例三、关键知识点总结四、进阶技巧五、实践建议多选题设计题代码测试说明 一、模板特化与重载的核心概念 函数模板重载 (Function Template Overloading) // 基础模板 template<typename…...

可视化动态表单动态表单界的天花板--Formily(阿里开源)

文章目录 1、Formily表单介绍2、安装依赖2.1、安装内核库2.2、 安装 UI 桥接库2.3、Formily 支持多种 UI 组件生态&#xff1a; 3、表单设计器3.1、核心理念3.2、安装3.3、示例源码 4、场景案例-登录注册4.1、Markup Schema 案例4.2、JSON Schema 案例4.3、纯 JSX 案例 1、Form…...

Amdahl 定律

Amdahl 定律是用来表示&#xff0c;当提高系统某部分性能时对整个系统的影响&#xff0c;其公式如下&#xff1a; a表示我们提升部分初始耗时比例&#xff0c;k是我们的提升倍率&#xff0c;通过这个公式我们可以轻松的得知对每一部分的提醒&#xff0c;对整个系统带来的影响…...

rust学习笔记19-泛型

Rust 的泛型&#xff08;Generics&#xff09;允许编写可复用的代码&#xff0c;通过抽象类型或行为来避免重复逻辑。 1. 泛型的基本使用 函数泛型 在函数中定义泛型参数&#xff0c;支持不同类型的数据操作&#xff1a; fn max<T: PartialOrd>(a: T, b: T) -> T …...

Linux系统之美:环境变量的概念以及基本操作

本节重点 理解环境变量的基本概念学会在指令和代码操作上查询更改环境变量环境变量表的基本概念父子进程间环境变量的继承与隔离 一、引入 1.1 自定义命令&#xff08;我们的exe&#xff09; 我们以往的Linux编程经验告诉我们&#xff0c;我们在对一段代码编译形成可执行文件后…...

数学爱好者写的编程系列文章

作为一个数学爱好者&#xff0c;我大学读的专业却不是数学专业&#xff0c;而是跟计算机有关的专业。原本我对编程一窍不通&#xff0c;平时上课也是在看数学文献&#xff0c;作业基本靠同学&#xff0c;考试及格就行。不过后来因为毕业的压力&#xff0c;我还是拥抱编程了&…...

pnpm 报错 Error: Cannot find matching keyid 解决

1. 查看corepack版本&#xff0c;升级至0.31.0 npm i -g corepack0.31.0 这里注意环境变量&#xff0c;可能升级后还是指向旧版本&#xff0c;可以选择更新环境变量或者删除原指向的corepack命令 2. 更新pnpm corepack install -g pnpmlatest 问题解决。...

dcat-admin已完成项目部署注意事项

必须 composer update 更新项目php artisan admin:publish 发布dcatadmin的静态资源手动创建目录&#xff08;如果没有&#xff09; storage/appstorage/framework/cachestorage/framework/sessionsstorage/framework/views 需检查 php不要禁用以下函数 putenvsymlinkproc_…...

Ubuntu实时读取音乐软件的音频流

文章目录 一. 前言二. 开发环境三. 具体操作四. 实际效果 一. 前言 起因是这样的&#xff0c;我需要在Ubuntu中&#xff0c;实时读取正在播放音乐的音频流&#xff0c;然后对音频进行相关的处理。本来打算使用的PipewireHelvum的方式实现&#xff0c;好处是可以直接利用Helvum…...

大语言模型进化论:从文本理解到多模态认知的革命之路

一、Transformer&#xff1a;认知革命的基石 ### 1.1 自注意力机制&#xff1a;神经网络的"量子纠缠" python # 自注意力核心公式实现 def self_attention(Q, K, V, maskNone): d_k Q.size(-1) scores torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(…...

《Operating System Concepts》阅读笔记:p460-p4470

《Operating System Concepts》学习第 36 天&#xff0c;p460-p4470 总结&#xff0c;总计 11 页。 一、技术总结 无。 二、英语总结(生词&#xff1a;3) 1.lifespan (1)lifespan: life span(“the period of time that sth exists or happens”) c. 也写作 life-span, …...

Postgresql 删除数据库报错

1、删除数据库时&#xff0c;报错存在其他会话连接 ## 错误现象&#xff0c;存在其他的会话连接正在使用数据库 ERROR: database "cs" is being accessed by other users DETAIL: There is 1 other session using the database.2、解决方法 ## 终止被删除数据库下…...

Fiddler抓包工具最快入门

目录 前言 了解HTTP网络知识 简单了解网络访问过程 简单了解HTTP网络传输协议 工作过程 HTTP请求&#xff1a; Fildder工具使用教程 抓包的概念 一、什么是抓包 二、为什么要抓包 三、抓包的原理&#xff08;图解&#xff09; Fiddler工具 安装 使用 Fiddler查看…...

编译器与中间表示:LLVM与GCC、G++、Clang的关系详解

编译器与中间表示&#xff1a;LLVM与GCC、G、Clang的关系详解 引言 编译器是软件开发中不可或缺的工具&#xff0c;它负责将高级语言&#xff08;如C/C、Java等&#xff09;转换为机器语言&#xff0c;使计算机能够理解和执行程序。中间表示&#xff08;Intermediate Represe…...

《深度剖析:鸿蒙系统不同终端设备的UI自适应布局策略》

在万物互联的时代&#xff0c;鸿蒙系统以其独特的分布式理念和强大的技术架构&#xff0c;迅速在智能终端领域崭露头角。随着鸿蒙生态的不断壮大&#xff0c;越来越多的开发者投身其中&#xff0c;致力于为用户打造丰富多样的应用体验。然而&#xff0c;如何让应用在不同终端设…...