3

Why can I skip calling log_func in yield log_func, i.e. I can just write yield and the code still works. Why is that? How does yield work in this case?

import time
from contextlib import contextmanager

@contextmanager
def log_exec(log_func):
    s = time.perf_counter()
    yield log_func
    e = time.perf_counter()
    log_func(e - s)

with log_exec(log.debug):
    time.sleep(1)
alex_noname
  • 26,459
  • 5
  • 69
  • 86
user270199
  • 905
  • 1
  • 6
  • 12

1 Answers1

2

Excerpt from the documentation:

This iterator must yield exactly one value, which will be bound to the targets in the with statement’s as clause, if any.

You are not using as clause, therefore the outcome is unchanged. But if you try to use it with an empty yield, you will see that the yielded value is None.

with log_exec(debug) as log_foo:
    print(log_foo)
    time.sleep(1)
alex_noname
  • 26,459
  • 5
  • 69
  • 86
  • So in this case, since the contextmanager requires an iterator, we have to yield, even though we're yielding nothing? This is probably more of a question about the implementation of this contextmanager. – user270199 Nov 13 '20 at 13:21
  • Yes, we have to yield exactly one value, even `None`. You can read more in this excellent [answer](https://stackoverflow.com/a/35489897/13782669) – alex_noname Nov 13 '20 at 13:24