@@ -316,6 +316,75 @@ expensive function in a table and use them directly instead of recomputing
316316them when they have already been computed. This is clearly not part
317317of the function logic.
318318
319+ Context Managers
320+ ----------------
321+
322+ A context manager is a Python object that provides extra contextual information
323+ to an action. This extra information takes the form of running a function upon
324+ initiating the context using the ``with `` statement as well as running a function
325+ upon completing all the code inside the ``with `` block. The most well known
326+ example of using a context manager is operating on a file:
327+
328+ .. code-block :: python
329+
330+ with open (' file.txt' ) as f:
331+ contents = f.read()
332+
333+ Anyone familiar with this pattern knows that invoking ``open `` in this fashion
334+ ensures that ``f ``'s ``close `` method will be called at some point. This reduces
335+ a developer's cognitive load and makes code easier to read.
336+
337+ There are two easy ways to implement this functionality yourself: using a class
338+ or using a generator. Let's implement the above functionality ourselves, starting
339+ with the class approach:
340+
341+ .. code-block :: python
342+
343+ class CustomOpen (object ):
344+ def __init__ (self , filename ):
345+ self .file = open (filename)
346+
347+ def __enter__ (self ):
348+ return self .file
349+
350+ def __exit__ (self , ctx_type , ctx_value , ctx_traceback ):
351+ self .file.close()
352+
353+ with CustomOpen(' file' ) as f:
354+ contents = f.read()
355+
356+ This is just a regular Python object with two extra methods that are used
357+ by the ``with `` statement. CustomOpen is first instantiated and then its
358+ ``__enter__ `` method is called and whatever ``__enter__ `` returns is assigned to
359+ ``f `` in the ``as f `` part of the statement. When the contents of the ``with `` block
360+ is finished executing, the ``__exit__ `` method is then called.
361+
362+ And now the generator approach using Python's own
363+ `contextlib <https://docs.python.org/2/library/contextlib.html >`_:
364+
365+ .. code-block :: python
366+
367+ from contextlib import contextmanager
368+
369+ @contextmanager
370+ def custom_open (filename ):
371+ f = open (filename)
372+ yield f
373+ f.close()
374+
375+ with custom_open(' file' ) as f:
376+ contents = f.read()
377+
378+ This works in exactly the same way as the class example above, albeit it's
379+ more terse. The ``custom_open `` function executes until it reaches the ``yield ``
380+ statement. It then gives control back to the ``with `` statement, which assigns
381+ whatever was ``yield ``'ed to `f ` in the ``as f `` portion.
382+
383+ Since the two approaches appear the same, we should follow the Zen of Python
384+ to decide when to use which. The class approach might be better if there's
385+ a considerable amount of logic to encapsulate. The function approach
386+ might be better for situations where we're dealing with a simple action.
387+
319388Dynamic typing
320389--------------
321390
0 commit comments