一个可以跳过它的块的with语句

时间:2013-12-11 14:59:55

标签: python generator contextmanager

我厌倦了编写像这样的Python(2.7)代码:

if "george" in cats and cats["george"] is not None:
    special_cat = cats["george"]
    # do something with special_cat

所以我写了一个返回零或一个对象的生成器:

def maybe_get(d, k):
    if k in d and d[k] is not None:
        yield d[k]
    else:
        return

现在我可以将更多原始代码段更紧凑,如下所示:

for special_cat in maybe_get(cats, "george"):
    # do something with special_cat

为此目的使用for循环看起来很奇怪。我更愿意使用上下文管理器:

with maybe_get(cats, "george") as special_cat:
    # do something with special_cat

但我无法弄清楚任何方法让上下文管理器跳过它管理的代码块。 (例如,如果生成器没有产生至少一个值,@contextmanager装饰器将引发RuntimeError。)是否有一个我不知道的技巧?

1 个答案:

答案 0 :(得分:3)

你不能使用上下文管理器来“跳过”代码块,这就是条件的含义。上下文管理器可以做的就是挂接块进入和退出信号,而不是控制是否首先输入了块。

我会用:

special_cat = cats.get("george")
if special_cat is not None:
    # do something with special_cat

这具有可读和简单的优点。任何带有生成器或上下文管理器的恶作剧都会增加代码新维护者的意外。请记住:在距离代码库一两年之后,您是一位新的维护者。