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
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
--------------