PEP: 203 Title: Augmented Assignments Version: $Revision$ Owner: thomas@xs4all.net (Thomas Wouters) 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 indent-tabs-mode: nil End: