【发布时间】:2017-05-06 05:34:03
【问题描述】:
假设我正在使用某种上下文管理器(来自第三方库):
with freeze_time(test_dt):
lines_of_code_1
lines_of_code_2
lines_of_code_3
但是,假设如果 test_dt 没有值,则上下文管理器不应该运行,但所有剩余的代码都应该运行,如下所示:
if test_dt:
with freeze_time(test_dt):
lines_of_code_1
lines_of_code_2
lines_of_code_3
else:
lines_of_code_1
lines_of_code_2
lines_of_code_3
假设lines_of_code 这里有 2-3 行完全相同的代码,有没有更简洁的写法?我知道我可以写这样的东西:
def do_thing():
lines_of_code_1
lines_of_code_2
lines_of_code_3
if test_dt:
with freeze_time(test_dt):
do_thing()
else:
do_thing()
但我并不喜欢这种格式。另外,我不想在我的代码中到处乱扔这种模式。
还有最后一种可能性,但我不确定它是否会起作用:如果给定的 test_dt 为空,则子类化上下文管理器并跳过 __enter__ 和 __exit__ 函数,如下所示:
class optional_freeze_time(object):
def __init__(self, test_dt=None):
if test_dt:
self.ctx_manager = freeze_time(test_dt)
else:
self.ctx_manager = None
def __enter__(self, *args, **kwargs):
if self.ctx_manager:
self.ctx_manager.__enter__(*args, **kwargs)
def __exit__(self, *args, **kwargs):
if self.ctx_manager:
self.ctx_manager.__exit__(*args, **kwargs)
我用一个空白的上下文管理器类对其进行了测试,它似乎表现正确。但是,我担心如果我这样做,真正的上下文管理器是否会正确运行(我不太熟悉它的内部工作原理)。
【问题讨论】:
-
你能举一个不那么抽象的例子吗?是的,您可以更改上下文管理器,使其在进入和退出
if input is None:时不执行任何操作。你测试过你写的东西吗? -
也许可以创建一个不执行任何操作的
blank_context_manager对象并覆盖context_manager.__new__以在没有输入的情况下返回空白,这会将条件数减少到 1。 -
@jonrsharpe 您希望代码的哪一部分不那么抽象?我宁愿不改变或触摸原来的上下文管理器。我将继续用我正在使用的实际上下文管理器替换代码,但我觉得这个概念本身可以适用于更一般的情况。
标签: python contextmanager