Why not an __assign__ method?

Robin Thomas robin900 at yahoo.com
Fri Apr 6 20:25:48 EDT 2001


At 07:40 PM 4/6/01 -0300, Carlos Alberto Reis Ribeiro wrote:
>I was travelling on the past two days, and I was really surprised to see 
>Robin Thomas and Roeland Rengelink proposals.

Hey, open source development moves fast. :)

>On the other hand Robin's code is transparent and generic, and it avoids 
>the problem of determining when an object is bound by cleverly checking 
>the reference count.

I've been trying to find a way to break the implementation, and I just 
can't. Weakrefs are not a problem. Creating an object via C API and then 
executing Python code involving that object is not a problem. I just can't 
find a way to make an object that ends up on a frame stack with ob_refcnt 
== 1 that is not an intermediate, temporary object that safely can do an 
in-place op.


>- Some mathematical operations cannot be done inplace. The best example 
>that I can think of is matrix multiplication (the "true" one, not the 
>scalar version). I'm sure there are lots of other mathematical operations 
>with this property. The inplace operator implementation needs to take care 
>of this anyway, so it may not be a problem.

Right. IIRC, the resulting object of an binary arithmetic op and its 
in-place counterpart must be equivalent by convention. Even for sequences. 
If an object decides *not* to obey these rules, it is exploiting the 
in-place operation in a spurious and unethical way.

>- Some class libraries do not implement the inplace version as of now. 
>There must be a mechanism to fall back to the binary operator version in 
>this case. (maybe this is already done - I will check the source for the 
>default inplace methods to see if they are calling the binary operators in 
>this case)

Check the source, Carlos!!! :-) The fallback to non-in-place operator is 
already there. That's why "a += 1" generates a STORE_* opcode at the end, 
so that the object produced by a fallback binary op will get bound to "a".


>- Check for any possible side effects for non commutative and/or non 
>transitive operations. This is probably not  a problem; I just want to be 
>on the safe side.

In their great wisdom -- and also because there's no damn way to do 
otherwise -- the Python gods specified in-place ops as non-commutative. 
Otherwise, how do you know which object will mutate?


>- The result of the inplace operator and the binary operator MUST be 
>exactly the same. If some class library "abuses" this in a non standard 
>way, it will break (with good reason).

Amen! My patch is actually a punishment mechanism that will create 
unexpected behavior for objects with abusive implementations. Then the 
authors will post to the c.l.python and be suitably re-educated.


>- Robin's proposal applies to *all* objects. We need to measure the 
>speedud of the proposed version to check if the economy in object 
>allocation makes up for the extra tests.

Doing "make test" on Python 2.1b1 generates hundreds of occurrences of the 
optimization case. *Hundreds*. Especially on re.compile().

The base cost of the patch is executing "if (ob->ob_refcnt == 1)". That's 
about as costly as a runtime type check, and only slightly more costly than 
Py_INCREF(ob). It's about as costly as Py_DECREF(ob) in the shortcut case. 
Not bad at all. (Some shortcut optimizations, like the integer addition, 
currently execute before the optimization check.)

Any object bound to a name (in any namespace, including the fastlocals 
tuple) does not engage the optimization. Any constant object (numeric, 
string, and unicode literals) always has an extra reference to it in the 
code object's co_consts tuple, so it does not engage the optimization. Of 
the built-in types, only tuples will cause PyNumber_InPlaceAdd() to 
fallback to regular add. I've been thinking about how to hack on tuples. 
Perhaps an extra check in the BINARY_ADD code to ensure that it's not a 
tuple is acceptable.

Instances are always much slower, because the InstanceType has to pretend 
it implements every operation. Even in these cases, if the instance really 
does support the in-place operation, it still saves the creation of some 
temporary instances.

The biggest gain is on temporary lists, which as "make test" reveals, are 
used one whole hell of a lot.


--
robin900 at yahoo.com


_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com





More information about the Python-list mailing list