Python 进行反射和元编程
反射和元编程是Python中两种强大且高级的编程技术。反射允许程序在运行时检查和修改自身结构和行为,而元编程则是编写可以操作其他代码的代码,通常通过使用元类、装饰器等技术来实现。
1. 反射
反射是指程序在运行时检查和操作自身结构的能力。Python通过内置的inspect模块以及一些内置函数提供了反射功能。
1.1 type()和id()
这两个函数用于获取对象的类型和唯一标识。
a = 42
print(type(a)) # <class 'int'>
print(id(a)) # 140731011254336
1.2 getattr(), setattr(), hasattr(), delattr()
这些函数允许动态获取、设置、检查和删除对象的属性。
class MyClass:def __init__(self):self.value = 42obj = MyClass()# 获取属性
print(getattr(obj, 'value')) # 42# 设置属性
setattr(obj, 'value', 100)
print(obj.value) # 100# 检查属性
print(hasattr(obj, 'value')) # True# 删除属性
delattr(obj, 'value')
print(hasattr(obj, 'value')) # False
1.3 dir()
dir()函数用于列出对象的所有属性和方法。
print(dir(obj)) # ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', ...]
1.4 inspect模块
inspect模块提供了更为详细的反射功能。
import inspectdef my_function():pass# 检查对象是否为函数
print(inspect.isfunction(my_function)) # True# 获取函数的源代码
print(inspect.getsource(my_function)) # 'def my_function():\n pass\n'
2. 元编程
元编程是指编写可以操作其他代码的代码。Python中的元编程主要包括元类、装饰器和类装饰器等技术。
2.1 元类
元类是用来创建类的类。通过自定义元类,我们可以在类创建时动态地修改类的行为。
# 自定义元类
class MyMeta(type):def __new__(cls, name, bases, dct):print(f'Creating class {name}')return super().__new__(cls, name, bases, dct)# 使用元类创建类
class MyClass(metaclass=MyMeta):def __init__(self):self.value = 42# 创建对象
obj = MyClass() # 输出:Creating class MyClass
元类的主要方法包括:
__new__:控制类的创建过程。__init__:初始化类。
2.2 装饰器
装饰器是修改函数或方法行为的函数。它们通常用于日志记录、权限检查、性能计数等。
def my_decorator(func):def wrapper(*args, **kwargs):print('Before function call')result = func(*args, **kwargs)print('After function call')return resultreturn wrapper@my_decorator
def say_hello(name):print(f'Hello, {name}!')say_hello('World') # 输出:Before function call, Hello, World!, After function call
2.3 类装饰器
类装饰器是修改类行为的函数。
def my_class_decorator(cls):class Wrapped(cls):def new_method(self):return 'This is a new method'return Wrapped@my_class_decorator
class MyClass:def __init__(self):self.value = 42obj = MyClass()
print(obj.new_method()) # 输出:This is a new method
3. 综合实例
我们将通过一个综合实例来演示反射和元编程的结合使用。假设我们需要一个记录日志的功能,当调用类的方法时,自动记录调用信息。
3.1 定义元类
首先,我们定义一个元类,在创建类时为每个方法添加日志记录功能。
class LoggingMeta(type):def __new__(cls, name, bases, dct):for key, value in dct.items():if callable(value):dct[key] = cls.log_decorator(value)return super().__new__(cls, name, bases, dct)@staticmethoddef log_decorator(func):def wrapper(*args, **kwargs):print(f'Calling {func.__name__} with args: {args}, kwargs: {kwargs}')return func(*args, **kwargs)return wrapper
3.2 定义使用元类的类
接着,我们定义一个类使用LoggingMeta元类。
class MyClass(metaclass=LoggingMeta):def method1(self, x):return x * 2def method2(self, y):return y + 100# 创建对象并调用方法
obj = MyClass()
print(obj.method1(10)) # 输出:Calling method1 with args: (<__main__.MyClass object at 0x000001>, 10)# 20
print(obj.method2(20)) # 输出:Calling method2 with args: (<__main__.MyClass object at 0x000001>, 20)# 120
4. 更进一步的元编程
元编程不仅限于上述的元类和装饰器,还包括创建DSL(领域特定语言)、AST(抽象语法树)操作等更高级的技术。
4.1 创建DSL
通过Python的灵活性,我们可以创建小型的DSL,用于特定的任务。例如,创建一个简单的计算器DSL:
class Calculator:def __init__(self):self.value = 0def add(self, x):self.value += xreturn selfdef subtract(self, x):self.value -= xreturn selfdef multiply(self, x):self.value *= xreturn selfdef divide(self, x):if x != 0:self.value /= xreturn selfdef result(self):return self.value# 使用DSL
calc = Calculator()
result = calc.add(5).multiply(2).subtract(3).divide(4).result()
print(result) # 输出:2.0
4.2 操作AST
Python的ast模块允许我们操作Python代码的抽象语法树,从而动态地生成和修改代码。
import ast# 解析Python代码为AST
code = "a = 1 + 2"
tree = ast.parse(code, mode='exec')# 遍历AST节点
class CodeTransformer(ast.NodeTransformer):def visit_BinOp(self, node):if isinstance(node.op, ast.Add):node.op = ast.Sub()return nodetransformer = CodeTransformer()
new_tree = transformer.visit(tree)# 将AST转回Python代码
new_code = compile(new_tree, filename="<ast>", mode="exec")
exec(new_code)
print(a) # 输出:-1
反射和元编程是Python中强大且灵活的编程技术。通过反射,我们可以动态地检查和操作对象;通过元编程,可以编写能够修改和生成代码的代码。这些技术不仅增强了代码的灵活性和可重用性,还为创建DSL和操作AST等高级应用提供了可能性。在实际开发中,合理使用这些技术可以极大地提升程序的扩展性和维护性。

相关文章:
Python 进行反射和元编程
反射和元编程是Python中两种强大且高级的编程技术。反射允许程序在运行时检查和修改自身结构和行为,而元编程则是编写可以操作其他代码的代码,通常通过使用元类、装饰器等技术来实现。 1. 反射 反射是指程序在运行时检查和操作自身结构的能力。Python通…...
Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N]……解决
一、问题 Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.二、解决方案 1、当打包构建的时候出现这个问题,如果你只是打包部署,那么就是将maven的test禁止可以成功打包 2、当你是本地服务器启动…...
如何看待“低代码”开发平台的兴起
目录 如何看待“低代码”开发平台的兴起?新机遇:效率与质量并进的新篇章1. 提升开发效率:2. 降低技术门槛:3. 创新加速: 挑战:质量和定制化需求的考量1. 定制能力受限:2. 依赖性和迁移成本 &…...
React类组件与函数组件有什么异同
相同点: 组件是react的最小代码片段,无论函数组件还是类组件 在使用方式 和 最终呈现效果是一致的类组件可以用函数组件重构,同样函数组件也可以用类组件重构(并不推荐),在现代浏览器中闭包 和 类的性能只…...
函数调用的过程理解_汇编角度
目录 1、调用函数流程(main函数调用print函数):Step1 保存main函数现场地址等信息Step2 跳转到print函数的位置Step3 执行print函数的指令Step4 返回main函数,执行下一条指令流程连续性总结 2、其他知识总结 1、调用函数流程&…...
【Java-一些常见单列集合面试问题】
目录 1.List,Set的区别? 2.ArrayList与Vector区别? 3.Arraylist与LinkedList区别? 4.ArrayList的扩容机制? 5.HashSet、LinkedHashSet和TreeSet 区别? 6.HashSet如何过滤重复元素? 1.List,Set的区别…...
搭建个人博客需要做哪些事
文章目录 前言搭建步骤站点服务器站点域名注册域名ICP 备案公安备案域名解析 博客图床图床是什么图床搭建 博客站点搭建建站工具本地搭建博客部署 站点运营百度收录百度统计 总结 前言 花了几天时间,搭建了一个个人博客,也算是完成了年初立的一个flag&a…...
《向量数据库指南》——非结构化数据的行业需求及向量数据库的关键角色
非结构化数据的行业需求及向量数据库的关键角色 引言 在当今数字化时代,数据已成为驱动社会进步与产业升级的核心要素。随着技术的飞速发展,特别是人工智能(AI)技术的广泛应用,数据的类型与规模正以前所未有的速度增长。其中,非结构化数据作为数据海洋中的主体部分,其…...
C++:map容器的使用
一、map的使用介绍 map文档介绍 1.1 map的模版参数 Key:键值对中Key的类型 T:键值对中value的类型 Compare:比较器的类型,map中的元素是按照Key来进行比较的,缺省情况(不传参数时)按照小于来…...
C++初学(10)
10.1、共用体 共用体是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型。比如说:结构可以同时存储int、long、和double,而共用体只能存储int、long、或double。共用体的句式与结构相似,但含义不…...
在MAC安装Lazarus 起点 - 我们的第一个Lazarus程序!
安装Lazarus 首先到Lazarus官网,找到合适的版本下载页面,比如Mac的版本: https://sourceforge.net/projects/lazarus/files/Lazarus%20macOS%20x86-64/Lazarus%203.4/ 将三个文件都下载到本地,需要安装这三个文件: …...
【每日刷题】Day96
【每日刷题】Day96 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. LCP 44. 开幕式焰火 - 力扣(LeetCode) 2. 1022. 从根到叶的二进制数之和 - …...
EGO-Swarm 仿真环境搭建
EGO-Swarm仿真环境搭建 参考教程: https://github.com/ZJU-FAST-Lab/ego-planner-swarm EGO-Swarm是一种分散的异步系统解决方案,用于仅使用机载资源在未知的障碍物丰富的场景中进行多机器人自主导航。 1. 查看系统环境 要运行本仿真程序,…...
【EI会议征稿通知】第九届计算机技术与机械电气工程国际学术论坛(ISCME 2024)
会议官网:www.is-cme.com 一轮截稿时间:2024年8月16日(早投稿,早录用) 大会时间:2024年11月8-10日 大会地点:中国 南京 接受/拒稿通知:投稿后1-2周 收录检索:EI Compend…...
【starRocks-docker 部署问题汇总】
Starrocks系列文章目录 例如:starrocks 常见问题汇总 文章目录 Starrocks系列文章目录前言一、Starrocks-be运行一段时间后,容器无法restart?二、等待后续跟新 前言 starrocks基于docker-compose部署的3节点分布式(3FE,3BE),遇到的问题也都…...
threejs中,如何检测一个模型周边一定范围内的其它模型
在Three.js中,要检测一个模型(我们可以称之为“主体模型”)周边一定范围内的其他物体,你可以通过以下步骤来实现: 1、定义检测范围: 首先,确定你需要检测的范围,这通常是一个以主体…...
UDP端口可达性检测(端口扫描)工具开发
UDP端口可达性检测(端口扫描)工具开发 1、应用场景分析 主机X与主机Y部署在AB双网环境下,两个主机间通过UDP协议进行数据交互。应用程序发送数据时,优先使用A网发送数据,如果A网异常则通过B网发送数据。两个主机应用间没有设置心跳帧 &…...
第三届计算、通信、感知与量子技术国际会议(CCPQT 2024)会议通知
会议信息 大会官网:http://www.ccpqt.org/ 官方邮箱:ccpqt_paper126.com 会议地点:中国珠海 会议时间:2024年10月25日-10月27日 主讲嘉宾 Prof. Trung Q. Duong IEEE Fellow and AAIA Fellow Memorial University of Newfoundl…...
Qt文件读写
Qt中文件读写类简述 包含头文件#include <QFile> 读写模式如下 枚举 文件读写步骤 1 先使用string 类型来接受打开文件的返回值 QFileDialog::getOpenFileName(this,"文件","./"); //打开一个文件 2 构建文件对象 Qfile ff (qstring)接受打…...
发现了一套超厉害的英语资料,绝对YYDS
昨某节目主持人与我闲聊英语学习的事情。 她工作数年,希望提升英文资讯的阅读能力。她主持的是中文节目,但节目对个人的知识广度和深度要求颇高。 现在的知识又太泛太杂,你需要了解国外最新资讯,多获得一手资料,面对节…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章 摘要: 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言,受限于 C 语言本身的内存安全和并发安全问题,开发复杂模块极易引入难以…...
Django RBAC项目后端实战 - 03 DRF权限控制实现
项目背景 在上一篇文章中,我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统,为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...
