Python导入模块时传递变量替代builtins实现跨文件装饰器调用
解决方案
你当前使用builtins注入全局对象的方式确实存在诸多问题:既污染全局命名空间,也没有类型提示支持,LSP自然会大量报错,且导入顺序出错就会直接触发运行时异常。以下方案完全保留你现有文件结构,不需要调整文件位置。
方案1:显式注册装饰器(最推荐,无LSP报错、完全符合Python规范)
这个方案只需要微调两个文件的代码,A.py完全不需要修改:
调整B.py代码
删除builtins导入,新增注册函数接收外部传入的装饰器:
def foo(): print("foo") def poo(): print("poo") # 新增注册方法,接收外部传入的实例装饰器 def register_decorator(decorator): global foo, poo # 批量替换已定义的函数为装饰后的版本 foo = decorator(foo) poo = decorator(poo)
调整main.py代码
删除builtins相关逻辑,实例化后主动调用注册方法即可:
from mylib.A import A import mylib.B as B a = A("This is printing in the decorator") # 传入实例的装饰器方法完成注册 B.register_decorator(a.our_decorator) B.foo() B.poo()
这个方案所有变量都是显式传递,类型可被LSP完全识别,不会有任何报错,也不存在全局污染的问题。
方案2:保留B.py的@装饰器写法
如果你习惯定义函数时用@语法标记需要装饰的函数,可以用延迟装饰的技巧,B.py代码调整如下:
# 临时装饰器,收集所有需要被装饰的函数 _decorate_list = [] def our_decorator(func): _decorate_list.append(func) return func @our_decorator def foo(): print("foo") @our_decorator def poo(): print("poo") def register_decorator(real_decorator): for func in _decorate_list: # 批量替换为装饰后的函数 globals()[func.__name__] = real_decorator(func)
main.py的用法和方案1完全一致,不需要修改。
内容的提问来源于stack exchange,提问作者Matteo Fiorina
相关产品推荐
相关产品推荐

