diff --git a/pep-0203.txt b/pep-0203.txt index b637e9266..1c89a3df9 100644 --- a/pep-0203.txt +++ b/pep-0203.txt @@ -6,6 +6,148 @@ Python-Version: 2.0 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 ' + ', the '__add__' + method should be defined. This method should return a new object, + which is the result of the expression. + + For the case of ' + ', 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