Addressed SF bug 421973 (finally).

Rewrote the subsection on coercion rules (and made it a proper
subsection, with a label).  The new section is much less precise,
because precise rules would be too hard to give (== I don't know what
they are any more :-).  OTOH, the new section gives much more
up-to-date information.

Also noted that __coerce__ may return NotImplemented, with the same
meaning as None.

I beg Fred forgiveness: my use of \code{} is probably naive.  Please
fix this and other markup nits.  An index entry would be nice.

This could be a 2.2 bugfix candidate, if we bother about old docs
(Fred?)
This commit is contained in:
Guido van Rossum 2002-06-03 19:06:41 +00:00
parent 40bbae3b03
commit 92cf95f45b
1 changed files with 88 additions and 46 deletions

View File

@ -1511,74 +1511,116 @@ the common type would be the type of \code{other}, it is sufficient to
return \code{None}, since the interpreter will also ask the other return \code{None}, since the interpreter will also ask the other
object to attempt a coercion (but sometimes, if the implementation of object to attempt a coercion (but sometimes, if the implementation of
the other type cannot be changed, it is useful to do the conversion to the other type cannot be changed, it is useful to do the conversion to
the other type here). the other type here). A return value of \code{NotImplemented} is
equivalent to returning \code{None}.
\end{methoddesc} \end{methoddesc}
\strong{Coercion rules}: to evaluate \var{x} \var{op} \var{y}, the \subsection{Coercion rules\label{coercion-rules}}
following steps are taken (where \method{__\var{op}__()} and
\method{__r\var{op}__()} are the method names corresponding to This section used to document the rules for coercion. As the language
\var{op}, e.g., if \var{op} is `\code{+}', \method{__add__()} and has evolved, the coercion rules have become hard to document
\method{__radd__()} are used). If an exception occurs at any point, precisely; documenting what one version of one particular
the evaluation is abandoned and exception handling takes over. implementation does is undesirable. Instead, here are some informal
guidelines regarding coercion. In Python 3.0, coercion will not be
supported.
\begin{itemize} \begin{itemize}
\item[0.] If \var{x} is a string object and \var{op} is the modulo \item
operator (\%), the string formatting operation is invoked and
the remaining steps are skipped.
\item[1.] If \var{x} is a class instance: If the left operand of a \% operator is a string or Unicode object, no
coercion takes place and the string formatting operation is invoked
instead.
\begin{itemize} \item
\item[1a.] If \var{x} has a \method{__coerce__()} method: It is no longer recommended to define a coercion operation.
replace \var{x} and \var{y} with the 2-tuple returned by Mixed-mode operations on types that don't define coercion pass the
\code{\var{x}.__coerce__(\var{y})}; skip to step 2 if the original arguments to the operation.
coercion returns \code{None}.
\item[1b.] If neither \var{x} nor \var{y} is a class instance \item
after coercion, go to step 3.
\item[1c.] If \var{x} has a method \method{__\var{op}__()}, return New-style classes (those derived from \code{object}) never invoke the
\code{\var{x}.__\var{op}__(\var{y})}; otherwise, restore \var{x} and \code{__coerce__} method in response to a binary operator; the only
\var{y} to their value before step 1a. time \code{__coerce__} is invoked is when the built-in function
\code{coerce()} is called.
\end{itemize} \item
\item[2.] If \var{y} is a class instance: For most intents and purposes, an operator that returns
\code{NotImplemented} is treated the same as one that is not
implemented at all.
\begin{itemize} \item
\item[2a.] If \var{y} has a \method{__coerce__()} method: Below, \method{__op__()} and \method{__rop__()} are used to signify
replace \var{y} and \var{x} with the 2-tuple returned by the generic method names corresponding to an operator;
\code{\var{y}.__coerce__(\var{x})}; skip to step 3 if the \method{__iop__} is used for the corresponding in-place operator. For
coercion returns \code{None}. example, for the operator `\code{+}', \method{__add__()} and
\method{__radd__()} are used for the left and right variant of the
binary operator, and \method{__iadd__} for the in-place variant.
\item[2b.] If neither \var{x} nor \var{y} is a class instance \item
after coercion, go to step 3.
\item[2b.] If \var{y} has a method \method{__r\var{op}__()}, For objects \var{x} and \var{y}, first \code{\var{x}.__op__(\var{y})}
return \code{\var{y}.__r\var{op}__(\var{x})}; otherwise, is tried. If this is not implemented or returns \code{NotImplemented},
restore \var{x} and \var{y} to their value before step 2a. \code{\var{y}.__rop__(\var{x})} is tried. If this is also not
implemented or returns \code{NotImplemented}, a \code{TypeError}
exception is raised. But see the following exception:
\end{itemize} \item
\item[3.] We only get here if neither \var{x} nor \var{y} is a class Exception to the previous item: if the left operand is an instance of
instance. a built-in type or a new-style class, and the right operand is an
instance of a proper subclass of that type or class, the right
operand's \code{__rop__} method is tried \emph{before} the left
operand's \code{__op__} method. This is done so that a subclass can
completely override binary operators. Otherwise, the left operand's
__op__ method would always accept the right operand: when an instance
of a given class is expected, an instance of a subclass of that class
is always acceptable.
\begin{itemize} \item
\item[3a.] If \var{op} is `\code{+}' and \var{x} is a When either operand type defines a coercion, this coercion is called
sequence, sequence concatenation is invoked. before that type's \code{__op__} or \code{__rop__} method is called,
but no sooner. If the coercion returns an object of a different type
for the operand whose coercion is invoked, part of the process is
redone using the new object.
\item[3b.] If \var{op} is `\code{*}' and one operand is a \item
sequence and the other an integer, sequence repetition is
invoked.
\item[3c.] Otherwise, both operands must be numbers; they are When an in-place operator (like `\code{+=}') is used, if the left
coerced to a common type if possible, and the numeric operand implements \code{__iop__}, it is invoked without any coercion.
operation is invoked for that type. When the operation falls back to \code{__op__} and/or \code{__rop__},
the normal coercion rules apply.
\end{itemize} \item
In \var{x}\code{+}\var{y}, if \var{x} is a sequence that implements
sequence concatenation, sequence concatenation is invoked.
\item
In \var{x}\code{*}\var{y}, if one operator is a sequence that
implements sequence repetition, and the other is an integer
(\code{int} or \code{long}), sequence repetition is invoked.
\item
Rich comparisons (implemented by methods \code{__eq__} and so on)
never use coercion. Three-way comparison (implemented by
\code{__cmp__}) does use coercion under the same conditions as
other binary operations use it.
\item
In the current implementation, the built-in numeric types \code{int},
\code{long} and \code{float} do not use coercion; the type
\code{complex} however does use it. The difference can become
apparent when subclassing these types. Over time, the type
\code{complex} may be fixed to avoid coercion. All these types
implement a \code{__coerce__} method, for use by the built-in
\code{coerce} function.
\end{itemize} \end{itemize}