문제

I got sick and tired of writing Python (2.7) code like this:

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

So I wrote a generator that returns either zero or one object:

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

Now I can make more original code snippet more compact, like so:

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

Using a for-loop for this purpose looks odd, though. I’d much rather use a context manager:

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

But I can’t figure out any way to make a context manager skip over the block of code it manages. (The @contextmanager decorator, for example, will raise a RuntimeError if the generator does not yield at least one value.) Is there a trick that I’m missing?

도움이 되었습니까?

해결책

You cannot use a context manager to 'skip' code blocks, that is what conditional are for. All a context manager can do is hook in to the block enter and exit signals, not control if the block is entered in the first place.

I'd use:

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

This has the advantage of being readable and simple. Any shenanigans with generators or context managers would increase the surprise for new maintainers of your code. And remember: you are a new maintainer after a year or two away from a codebase too.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top