如何在条件下插入 'with' 语句?

How can I insert a 'with' statement under a condition?

我有一段代码是这样构造的:

try:
    from tqdm import tqdm
    use_tqdm = True
except ImportError:
    use_tqdm = False


if use_tqdm:
    with tqdm(total=5) as pbar:
        # --- many nested for loops ---
        pbar.update(1)
else:
    # --- identical nested for loops, without pbar.update(1) ---

如何避免重复上述长代码块?

我不能把条件只放在里面的单个 pbar 行上,因为 tqdm 做的是创建一个进度条,所以它只需要实例化一次。

我想我正在寻找一种方法来告诉 Python“嘿,仅当 use_tqdm = True 时才考虑 with 语句,否则就假装它不存在”,但非常欢迎任何其他建议.

谢谢!

(tqdm 包:https://github.com/tqdm/tqdm

所以这里有两个不同的问题:

  • 重复但非常相似的代码
  • 有条件分配资源

对于第一个,定义一个函数,该函数可以选择接受 pbar 并默认为表示“忽略我”的信号。正如@Michael-Butscher 所建议的那样,要么创建一个虚拟 class,它在您希望忽略的所有函数中只有一个 pass,或者更脏一点,只是用 [=14= 来防止出现].示例:

class PbarDummy:
    def update(self, _):
        pass

def many_for_loops(pbar=PbarDummy()):
   --- many nested for loops ---
      pbar.update(1)

这也解决了你的第二个问题,因为你可以有条件地调用或不调用 with 块内的函数。

if use_tqdm:
   with tqdm(total = 5) as pbar:
      many_for_loops(pbar=pbar)
else:
   many_for_loops()

您可以为输入为 pbar 的嵌套 for 循环创建一个函数。在该函数内部,您检查传入的 pbar 是否为 None 表示不更新进度条,否则使用它并调用 update:

try:
    from tqdm import tqdm
    use_tqdm = True
except ImportError:
    use_tqdm = False

def process_nested_for_loops(pbar):
    # --- many nested for loops ---
        if pbar is not None:
            pbar.update(1)


if use_tqdm = True:
   with tqdm(total = 5) as pbar:
       process_nested_for_loops(pbar)
else:
   process_nested_for_loops(None)
try:
    from tqdm import tqdm
except ImportError:
    class tqdm:
        def __int__(self, *args, **kwargs):
            pass

        def __enter__(self):
            class Dummy:
                def update(self, *args, **kwargs):
                    pass

            return Dummy()

        def __exit__(self, *args):
            pass

with tqdm(total = 5) as pbar:
   --- many nested for loops ---
            pbar.update(1)

如果导入失败,您只会得到一个虚拟上下文和一个 update 方法是 no-op 的对象。不需要单独的代码。