Incomplete version of the augmented assignment PEP. It currently includes

only the arguments for/against inclusion of augmented assignment in Python,
not yet the technical details. I decided to upload this half-completed
version to give people some time to respond before I finish it :-)

Feel free to bring up any and all arguments. The point of the PEP is to
archive those, after all!
This commit is contained in:
Thomas Wouters 2000-07-16 16:07:29 +00:00
parent 685d4508ed
commit cf9d818d03
1 changed files with 142 additions and 0 deletions

View File

@ -6,6 +6,148 @@ Python-Version: 2.0
Status: Incomplete Status: Incomplete
Introduction
This PEP describes the `augmented assignment' proposal for Python
2.0. This PEP tracks the status and ownership of this feature,
slated for introduction in Python 2.0. It contains a description
of the feature and outlines changes necessary to support the
feature. This PEP summarizes discussions held in mailing list
forums, and provides URLs for further information, where
appropriate. The CVS revision history of this file contains the
definitive historical record.
The Origin of Augmented Assignment
Augmented assignment refers to binary operators that combine two
existing operators: the assignment operator, and one of the binary
operators. Its origins lie in other programming languages, most
notably `C', where it was defined for performance reasons. They
are meant to replace the repetetive syntax of, for instance,
adding the number '1' to a variable:
x = x + 1;
with an expression that is shorter, less error-prone and easier to
optimize (by the compiler):
x += 1;
The same goes for all other binary operands, resulting in the
following augmented assignment operator list, based on Python's
current binary operator list:
+=, -=, /=, *=, %=, **=, >>=, <<=, &=, |=, ^=
See the documentation of each operator on what they do.
Augmented Assignment in Python
The traditional reasons for augmented assignment, readability and
optimization, are not as obvious in Python, for several reasons.
- Numbers are immutable, they cannot be changed. In other
programming languages, a variable holds a value, and altering
the variable changes the value it holds. In Python, variables
hold `references' to values, and altering an immutable value
means changing the variable, not what it points to.
- Assignment is a different operation in Python. In most
languages, variables are containers, and assignment copies a
value into that container. In Python, assignment binds a value
to a name, it does not copy the value into a new storage space.
- The augmented assignment operators map fairly directly into the
underlying hardware. Python does not deal directly with the
hardware it runs on, so this `natural inclusion' does not make
sense.
- The augmented assigment syntax is subtly different in more
complex expressions. What to do, for instance, in a case such
as this:
seq[i:calc(seq, i)] *= r
It is unclear whether 'seq' gets indexed once or twice, and
whether 'calc' gets called once or twice.
Normal operators
There are, however, good reasons to include augented assignment.
One of these has to do with Python's way of handling operators. In
Python, a user defined class can implement one or more of the
binary operators by supplying a 'magic' method name. For instance,
for a class to support '<instance> + <object>', the '__add__'
method should be defined. This method should return a new object,
which is the result of the expression.
For the case of '<object> + <instance>', where 'object' does not
have an '__add__' method, the class can define a '__radd__'
method, which then should behave exactly as '__add__'. Indeed,
'__radd__' is often a different name for the same method.
For C extention types, a similar technique is available, through
the PyNumberMethods and PySequenceMethods members of the PyType
structure.
However, the problem with this approach is that the '__add__'
method cannot know in what context it is called. It cannot tell
whether it should create a new object, or whether it is allowed to
modify itself. (As would be the case in 'x = x + 1') As a result,
the '__add__' method, and all other such 'magic' methods, should
always return a new object. For large objects, this can be very
inefficient.
This inefficiency is often solved by adding a method that does the
appropriate modification 'in-place'. List objects, for instance,
have the 'extend' method that behaves exactly as the '+' operator,
except the operation is done on the list itself, instead of on a
copy.
The augmented assignment syntax can support this behaviour
explicitly. When the magic method for 'in-place' operation are
missing, it can fall back to the normal methods for that
operation, maintaining full backward compatibility even when
mixing the new syntax with old objects.
The other benifit of augmented assignment is readability. After
the general concept of augmented assignment is grasped, all the
augmented assigment operators instantly become obvious. There is
no need for non-obvious and non-standard method names to implement
efficient, in-place operations, and there is no need to check the
type of an object before operating on it: the augmented assignment
will work for all types that implement that basic operation, not
merely those that implement the augmented variant.
And the last problem with augmented assignment, what to do with
indexes and function calls in the expression, can be solved in a
very Pythonic manner: if it looks like it's only called once, it
*is* only called once. Taking this expression:
seq[func(x)] += x
The function 'func' is called once, and 'seq' is indexed twice:
once to retrieve the value (__getitem__), and once to store it
(__setitem__). So the expression can be rewritten as:
tmp = func(x)
seq[tmp] = seq[tmp] + x
The augmented assignment form of this expression is much more
readable.
Local Variables: Local Variables:
mode: indented-text mode: indented-text