Edits, using the new term

'context specifier' in a few places
This commit is contained in:
Andrew M. Kuchling 2006-04-24 14:30:47 +00:00
parent a6c67b56b2
commit 0a7ed8c2d3
1 changed files with 31 additions and 29 deletions

View File

@ -579,13 +579,12 @@ Sugalski.}
%====================================================================== %======================================================================
\section{PEP 343: The 'with' statement\label{pep-343}} \section{PEP 343: The 'with' statement\label{pep-343}}
The '\keyword{with}' statement allows a clearer version of code that The '\keyword{with}' statement clarifies code that previously would
uses \code{try...finally} blocks to ensure that clean-up code is use \code{try...finally} blocks to ensure that clean-up code is
executed. executed. In this section, I'll discuss the statement as it will
commonly be used. In the next section, I'll examine the
In this section, I'll discuss the statement as it will commonly be implementation details and show how to write objects for use with this
used. In the next section, I'll examine the implementation details statement.
and show how to write objects for use with this statement.
The '\keyword{with}' statement is a new control-flow structure whose The '\keyword{with}' statement is a new control-flow structure whose
basic structure is: basic structure is:
@ -660,21 +659,22 @@ with decimal.Context(prec=16):
Under the hood, the '\keyword{with}' statement is fairly complicated. Under the hood, the '\keyword{with}' statement is fairly complicated.
Most people will only use '\keyword{with}' in company with existing Most people will only use '\keyword{with}' in company with existing
objects and don't need to know these details, so you can skip the objects and don't need to know these details, so you can skip the rest
following section if you like. Authors of new objects will need to of this section if you like. Authors of new objects will need to
understand the details of the underlying implementation. understand the details of the underlying implementation and should
keep reading.
A high-level explanation of the context management protocol is: A high-level explanation of the context management protocol is:
\begin{itemize} \begin{itemize}
\item The expression is evaluated and should result in an object \item The expression is evaluated and should result in an object
with a \method{__context__()} method. with a \method{__context__()} method (called a ``context specifier'').
\item This object's \method{__context__()} method is called, and must \item The context specifier's \method{__context__()} method is called,
return another object that has \method{__enter__()} and and must return another object (called a ``context manager'') that has
\method{__exit__()}. \method{__enter__()} and \method{__exit__()} methods.
\item This object's \method{__enter__()} method is called. The value \item The context manager's \method{__enter__()} method is called. The value
returned is assigned to \var{VAR}. If no \code{'as \var{VAR}'} clause returned is assigned to \var{VAR}. If no \code{'as \var{VAR}'} clause
is present, the value is simply discarded. is present, the value is simply discarded.
@ -725,14 +725,14 @@ First, the \class{DatabaseConnection} needs a \method{__context__()}
method. Sometimes an object can simply return \code{self}; the method. Sometimes an object can simply return \code{self}; the
\module{threading} module's lock objects do this, for example. For \module{threading} module's lock objects do this, for example. For
our database example, though, we need to create a new object; I'll our database example, though, we need to create a new object; I'll
call this class \class{DatabaseContext}. Our \method{__context__()} call this class \class{DatabaseContextMgr}. Our \method{__context__()}
method must therefore look like this: method must therefore look like this:
\begin{verbatim} \begin{verbatim}
class DatabaseConnection: class DatabaseConnection:
... ...
def __context__ (self): def __context__ (self):
return DatabaseContext(self) return DatabaseContextMgr(self)
# Database interface # Database interface
def cursor (self): def cursor (self):
@ -743,12 +743,12 @@ class DatabaseConnection:
"Rolls back current transaction" "Rolls back current transaction"
\end{verbatim} \end{verbatim}
Instance of \class{DatabaseContext} need the connection object so that Instance of \class{DatabaseContextMgr} need the connection object so that
the connection object's \method{commit()} or \method{rollback()} the connection object's \method{commit()} or \method{rollback()}
methods can be called: methods can be called:
\begin{verbatim} \begin{verbatim}
class DatabaseContext: class DatabaseContextMgr:
def __init__ (self, connection): def __init__ (self, connection):
self.connection = connection self.connection = connection
\end{verbatim} \end{verbatim}
@ -760,7 +760,7 @@ then add \code{as cursor} to their '\keyword{with}' statement to bind
the cursor to a variable name. the cursor to a variable name.
\begin{verbatim} \begin{verbatim}
class DatabaseContext: class DatabaseContextMgr:
... ...
def __enter__ (self): def __enter__ (self):
# Code to start a new transaction # Code to start a new transaction
@ -772,13 +772,15 @@ The \method{__exit__()} method is the most complicated because it's
where most of the work has to be done. The method has to check if an where most of the work has to be done. The method has to check if an
exception occurred. If there was no exception, the transaction is exception occurred. If there was no exception, the transaction is
committed. The transaction is rolled back if there was an exception. committed. The transaction is rolled back if there was an exception.
Here the code will just fall off the end of the function, returning
the default value of \code{None}. \code{None} is false, so the exception In the code below, execution will just fall off the end of the
will be re-raised automatically. If you wished, you could be more explicit function, returning the default value of \code{None}. \code{None} is
and add a \keyword{return} at the marked location. false, so the exception will be re-raised automatically. If you
wished, you could be more explicit and add a \keyword{return}
statement at the marked location.
\begin{verbatim} \begin{verbatim}
class DatabaseContext: class DatabaseContextMgr:
... ...
def __exit__ (self, type, value, tb): def __exit__ (self, type, value, tb):
if tb is None: if tb is None:
@ -830,8 +832,8 @@ with db_transaction(db) as cursor:
\end{verbatim} \end{verbatim}
You can also use this decorator to write the \method{__context__()} You can also use this decorator to write the \method{__context__()}
method for a class without creating a new class to act as the context method for a class without having to create a new class representing
manager: the context manager:
\begin{verbatim} \begin{verbatim}
class DatabaseConnection: class DatabaseConnection:
@ -1262,8 +1264,8 @@ which is also written in C but doesn't match the \module{profile}
module's interface, will continue to be maintained in future versions module's interface, will continue to be maintained in future versions
of Python. (Contributed by Armin Rigo.) of Python. (Contributed by Armin Rigo.)
Also, the \module{pstats} module used to analyze the data measured by Also, the \module{pstats} module for analyzing the data measured by
the profiler now supports directing the output to any file stream the profiler now supports directing the output to any file object
by supplying a \var{stream} argument to the \class{Stats} constructor. by supplying a \var{stream} argument to the \class{Stats} constructor.
(Contributed by Skip Montanaro.) (Contributed by Skip Montanaro.)