Adds context manager section to structure.rst

This commit is contained in:
sirMackk
2015-10-22 07:55:18 +02:00
parent 877ad38540
commit 77cf4f478d
+69
View File
@@ -316,6 +316,75 @@ expensive function in a table and use them directly instead of recomputing
them when they have already been computed. This is clearly not part them when they have already been computed. This is clearly not part
of the function logic. of the function logic.
Context Managers
----------------
A context manager is a Python object that provides extra contextual information
to an action. This extra information takes the form of running a function upon
initiating the context using the ``with`` statement as well as running a function
upon completing all the code inside the ``with`` block. The most well known
example of using a context manager is operating on a file:
.. code-block:: python
with open('file.txt') as f:
contents = f.read()
Anyone familiar with this pattern knows that invoking ``open`` in this fashion
ensures that ``f``'s ``close`` method will be called at some point. This reduces
a developer's cognitive load and makes code easier to read.
There are two easy ways to implement this functionality yourself: using a class
or using a generator. Let's implement the above functionality ourselves, starting
with the class approach:
.. code-block:: python
class CustomOpen(object):
def __init__(self, filename):
self.file = open(filename)
def __enter__(self):
return self.file
def __exit__(self, ctx_type, ctx_value, ctx_traceback):
self.file.close()
with CustomOpen('file') as f:
contents = f.read()
This is just a regular Python object with two extra methods that are used
by the ``with`` statement. CustomOpen is first instantiated and then its
``__enter__`` method is called and whatever ``__enter__`` returns is assigned to
``f`` in the ``as f`` part of the statement. When the contents of the ``with`` block
is finished executing, the ``__exit__`` method is then called.
And now the generator approach using Python's own
`contextlib <https://docs.python.org/2/library/contextlib.html>`_:
.. code-block:: python
from contextlib import contextmanager
@contextmanager
def custom_open(filename):
f = open(filename)
yield f
f.close()
with custom_open('file') as f:
contents = f.read()
This works in exactly the same way as the class example above, albeit it's
more terse. The ``custom_open`` function executes until it reaches the ``yield``
statement. It then gives control back to the ``with`` statement, which assigns
whatever was ``yield``'ed to `f` in the ``as f`` portion.
Since the two approaches appear the same, we should follow the Zen of Python
to decide when to use which. The class approach might be better if there's
a considerable amount of logic to encapsulate. The function approach
might be better for situations where we're dealing with a simple action.
Dynamic typing Dynamic typing
-------------- --------------