[Python-checkins] CVS: python/nondist/peps pep-0203.txt,1.2,1.3
Thomas Wouters
python-dev@python.org
Sun, 16 Jul 2000 09:07:31 -0700
Update of /cvsroot/python/python/nondist/peps
In directory slayer.i.sourceforge.net:/tmp/cvs-serv29324
Modified Files:
pep-0203.txt
Log Message:
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!
Index: pep-0203.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0203.txt,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** pep-0203.txt 2000/07/14 03:30:20 1.2
--- pep-0203.txt 2000/07/16 16:07:29 1.3
***************
*** 8,11 ****
--- 8,153 ----
+ 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:
mode: indented-text