You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何动态生成嵌套with语句?基于列表实现patch.object批量嵌套

如何用列表生成嵌套with语句(模拟多层patch.object)

针对你需要把列表中的模块-类对转换成嵌套with patch.object的需求,这里有两种实用的实现方式,效果和手动写多层嵌套完全一致:

方法一:用ExitStack管理多个上下文(推荐)

Python的contextlib.ExitStack专门用来动态管理多个上下文管理器,它会按顺序进入每个上下文,退出时逆序清理,和手动嵌套的逻辑完全匹配。

示例代码

from contextlib import ExitStack
from unittest.mock import patch
import importlib

# 你的模块-类列表
patch_targets = [("module1", "cls1"), ("module2", "cls2"), ("module3", "cls3")]

with ExitStack() as stack:
    # 遍历列表,逐个注册patch上下文
    for module_name, cls_name in patch_targets:
        # 动态导入模块(如果模块没提前导入的话)
        module = importlib.import_module(module_name)
        # 获取目标类
        target_cls = getattr(module, cls_name)
        # 将patch加入ExitStack
        stack.enter_context(patch.object(target_cls, "foo"))
    
    # 这里写原本放在嵌套with里的业务逻辑
    print("所有patch已生效,执行操作...")
    # do something

说明

  • 不需要手动写多层嵌套,列表多长就自动处理多少层
  • 异常情况下也能保证所有上下文按逆序正确退出,和手动嵌套的行为一致
  • 如果模块已经提前导入,也可以直接用globals()[module_name]代替importlib.import_module

方法二:用reduce手动嵌套(不推荐,可读性差)

如果不想用ExitStack,也可以用functools.reduce来手动嵌套上下文管理器,但这种方式可读性不如ExitStack,且需要注意异常处理:

示例代码

from functools import reduce
from unittest.mock import patch
import importlib

patch_targets = [("module1", "cls1"), ("module2", "cls2"), ("module3", "cls3")]

# 先创建所有patch上下文对象
patch_contexts = []
for module_name, cls_name in patch_targets:
    module = importlib.import_module(module_name)
    target_cls = getattr(module, cls_name)
    patch_contexts.append(patch.object(target_cls, "foo"))

# 定义要执行的业务函数
def do_something():
    print("执行操作...")
    # 你的业务逻辑

# 用reduce实现嵌套上下文
def run_with_nested_contexts(contexts, func):
    def wrap(ctx):
        with ctx:
            return func()
    # 从最后一个上下文开始嵌套,模拟手动从内到外的写法
    return reduce(lambda f, ctx: lambda: wrap(ctx) or f(), reversed(contexts), lambda: func())()

# 执行
run_with_nested_contexts(patch_contexts, do_something)

说明

  • 这种方式是通过函数嵌套模拟with语句的嵌套,逻辑和手动写多层with一致,但代码更绕,维护成本高
  • 除非有特殊场景,否则优先用ExitStack

内容的提问来源于stack exchange,提问作者Dejan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 09:54:18