Python中实现类似C++宏预处理指令的等价方案是什么
你觉得这段逻辑没法抽成公共函数,本质是直接封装的话,extract_stack(limit=2)会抓到公共函数自己的栈帧,拿不到外层赋值位置的代码。只要手动指定栈帧的起始偏移,跳过公共函数自身的栈层,完全可以正常封装复用,根本不需要类C的宏特性。
封装带栈偏移的公共函数(最推荐,零额外成本)
借助sys._getframe()直接定位到调用方的上层栈帧,跳过公共函数自身的栈层,就能拿到正确的赋值位置代码,和你把代码直接写在原地的效果完全一致,参考实现:from traceback import extract_stack, format_list import sys def get_assign_name(up_level: int = 1): # up_level+1 用于跳过当前get_assign_name函数自身的栈帧 target_frame = sys._getframe(up_level + 1) stack_info = format_list(extract_stack(target_frame, limit=1)) return stack_info[0].split('\n')[1].strip().split("=")[0].strip()使用时直接在需要的位置调用即可,不需要修改原有业务逻辑:
class Pmf: def __init__(self, name=None, ...): if not name: name = get_assign_name() # 原有业务逻辑类C宏的文本替换方案
如果一定要追求和C宏完全一致的原地文本展开效果,可以用支持宏定义的Python预处理第三方库,提前把你要复用的代码段定义成宏,运行前先做文本替换,把宏直接展开到对应位置,不会新增运行时栈层。缺点是需要给项目加预处理步骤,接入打包、运行流程,相对麻烦。PyCharm原生代码片段方案
如果不想改代码结构,就想省掉复制粘贴的麻烦,直接用PyCharm自带的代码模板功能就行:打开设置找到Editor下的Live Templates,选Python语境新建模板,设置一个好记的缩写(比如fillname),模板内容粘你那段重复的代码,保存之后只要在写代码的地方输缩写按Tab,代码就自动插进去了,和你手动粘贴的效果完全一样。装饰器统一注入方案
如果你这十多处复用的位置全是类的__init__方法,还可以写个装饰器把这段逻辑统一收了,连函数调用都不用重复写。注意装饰器本身会多一层栈帧,取栈的时候把limit参数对应加1,或者用sys._getframe调准偏移就行。
优先选第一种封装公共函数的方案,没有任何额外依赖,后续要改逻辑只需要改一个地方,维护成本最低。宏替换、IDE片段本质还是在多处插入重复代码,后续改逻辑容易漏,除非有特殊需求否则不推荐。
内容的提问来源于stack exchange,提问作者u2gilles

