5.4. Optimization Context Managers
Context Managers
In Python, context managers are implemented using the with statement.
The with statement provides a way to wrap a block of code with methods
defined by a context manager. When the block of code is entered, the
__enter__() method of the context manager is called, and when the block
of code is exited, the __exit__() method is called.
5.4.1. Contex Manager
We need to import time() function to get current timestamp
(number of seconds from 1970-01-01 00:00:00 UTC):
>>> from time import time
Define our context manager:
>>> class Timeit:
... def __enter__(self):
... self.start = time()
...
... def __exit__(self, *args):
... self.stop = time()
... duration = self.stop - self.start
... print(f'Duration: {duration:.4f} seconds')
>>> #
... with Timeit():
... result = [x**x for x in range(0, 10_000)]
...
Duration: 5.9882 seconds
5.4.2. Context Decorator Class
Inherit from
contextlib.ContextDecoratorClass become context manager decorator
Mind the brackets in decorator
@Timeit()
We need to import time() function to get current timestamp
(number of seconds from 1970-01-01 00:00:00 UTC). Moreover,
this time we need also contextlib.ContextDecorator for our
class to inherit from:
>>> from time import time
>>> from contextlib import ContextDecorator
Define our context manager:
>>> class Timeit(ContextDecorator):
... def __enter__(self):
... self.start = time()
...
... def __exit__(self, *args):
... self.stop = time()
... duration = self.stop - self.start
... print(f'Duration: {duration:.4f} seconds')
Define the function which will be automatically wrapped by context manager.
Mind the brackets in @Timeit():
>>> @Timeit()
... def run():
... result = [x**x for x in range(0, 10_000)]
Calling function will result in executing context manager:
>>> run()
Duration: 5.9302 seconds
5.4.3. Context Decorator Function
Split function for parts before and after
yieldCode before
yieldbecomes__enter__()Code after
yieldbecomes__exit__()
We need to import time() function to get current timestamp
(number of seconds from 1970-01-01 00:00:00 UTC):
>>> from time import time
>>> from contextlib import contextmanager
Define our context manager. Mind that Python will split our function
for parts before and after yield. Code before yield becomes
__enter__() and code after yield becomes __exit__():
>>> @contextmanager
... def timeit():
... start = time()
... yield
... end = time()
... duration = stop - start
... print(f'Duration: {duration:.4f} seconds')
Now we can use our function as a context manager:
>>> with timeit():
... result = [x**x for x in range(0, 10_000)]
...
Duration 4.0250 seconds