From f32f15658a7c3eea5976d87a0b0bf8eb91d01b29 Mon Sep 17 00:00:00 2001 From: Thomas Wouters Date: Fri, 25 Aug 2000 11:11:25 +0000 Subject: [PATCH] Update PEP to reflect reality. Explain the current mechanism the InPlace functions use to find the right function to call, and when to coerce or not. --- pep-0203.txt | 97 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 28 deletions(-) diff --git a/pep-0203.txt b/pep-0203.txt index 3baafbb2b..551543f58 100644 --- a/pep-0203.txt +++ b/pep-0203.txt @@ -63,25 +63,76 @@ Proposed semantics x += y tries to call x.__iadd__(y), which is the `in-place' variant of - __add__. If __iadd__ is not present, x.__add__(y) is - attempted, and finally y.__radd__(x) if __add__ is missing too. - There is no `right-hand-side' variant of __iadd__, because that - would require for `y' to know how to in-place modify `x', which is - unsafe to say the least. The __iadd__ hook should behave similar - to __add__, returning the result of the operation (which could be - `self') which is to be stored in the variable `x'. + __add__. If __iadd__ is not present, x.__add__(y) is attempted, + and finally y.__radd__(x) if __add__ is missing too. There is no + `right-hand-side' variant of __iadd__, because that would require + for `y' to know how to in-place modify `x', which is unsafe to say + the least. The __iadd__ hook should behave similar to __add__, + returning the result of the operation (which could be `self') + which is to be assigned to the variable `x'. For C extension types, the `hooks' are members of the - PyNumberMethods and PySequenceMethods structures, and are called - in exactly the same manner as the existing non-inplace operations, - including argument coercion. C methods should also take care to - return a new reference to the result object, whether it's the same - object or a new one. So if the original object is returned, it - should be INCREF()'d appropriately. + PyNumberMethods and PySequenceMethods structures. Some special + semantics apply to make the use of these methods, and the mixing + of Python instance objects and C types, as unsurprising as + possible. + + In the generic case of `x y' (or a similar case using the + PyNumber_InPlace API functions) the principal object being + operated on is `x'. This differs from normal binary operations, + where `x' and `y' could be considered `co-operating', because + unlike in binary operations, the operands in an in-place operation + cannot be swapped. However, in-place operations do fall back to + normal binary operations when in-place modification is not + supported, resuling in the following rules: + + - If the left-hand object (`x') is an instance object, and it + has a `__coerce__' method, call that function with `y' as the + argument. If coercion succeeds, and the resulting left-hand + object is a different object than `x', stop processing it as + in-place and call the appropriate function for the normal binary + operation, with the coerced `x' and `y' as arguments. The result + of the operation is whatever that function returns. + + If coercion does not yield a different object for `x', or `x' + does not define a `__coerce__' method, and `x' has the + appropriate `__ihook__' for this operation, call that method + with `y' as the argument, and the result of the operation is + whatever that method returns. + + - Otherwise, if the left-hand object is not an instance object, + but its type does define the in-place function for this + operation, call that function with `x' and `y' as the arguments, + and the result of the operation is whatever that function + returns. + + Note that no coercion on either `x' or `y' is done in this case, + and it's perfectly valid for a C type to receive an instance + object as the second argument; that is something that cannot + happen with normal binary operations. + + - Otherwise, process it exactly as a normal binary operation (not + in-place), including argument coercion. In short, if either + argument is an instance object, resolve the operation through + `__coerce__', `__hook__' and `__rhook__'. Otherwise, both + objects are C types, and they are coerced and passed to the + appropriate function. + + - If no way to process the operation can be found, raise a + TypeError with an error message specific to the operation. + + - Some special casing exists to account for the case of `+' and + `*', which have a special meaning for sequences: for `+', + sequence concatenation, no coercion what so ever is done if a C + type defines sq_concat or sq_inplace_concat. For `*', sequence + repeating, `y' is converted to a C integer before calling either + sq_inplace_repeat and sq_repeat. This is done even if `y' is an + instance, though not if `x' is an instance. + + The in-place function should always return a new reference, either + to the old `x' object if the operation was indeed performed + in-place, or to a new object. - [XXX so I am accepting this, but I'm a bit worried about the - argument coercion. For x+=y, if x supports augmented assignment, - y should only be cast to x's type, not the other way around!] Rationale @@ -133,7 +184,7 @@ Rationale Augmented assignment won't solve all the problems for these packages, since some operations cannot be expressed in the limited set of binary operators to start with, but it is a start. A - different PEP[3] is looking at adding new operators. + different PEP[2] is looking at adding new operators. New methods @@ -194,7 +245,7 @@ New methods Implementation - The current implementation of augmented assignment[2] adds, in + The current implementation of augmented assignment[1] adds, in addition to the methods and slots already covered, 13 new bytecodes and 13 new API functions. @@ -272,16 +323,6 @@ Open Issues bytecode at this time. - It is not possible to do an inplace operation in the variant of - - += - - Instead, the instance objects' __radd__ hook is called, with the - builtin type as argument. The same goes for the other operations. - It might necessary to add a right-hand version of __add_ab__ after - all, to support something like that. - - Copyright This document has been placed in the public domain.