[Python-ideas] Method chaining notation
Ron Adam
ron3200 at gmail.com
Tue Feb 25 21:55:58 CET 2014
On 02/24/2014 01:59 PM, Masklinn wrote:
>> >By using the '.' we can see the difference. The byte code should be very close to this, even though this function will give an error if you try to run it. (Can't update None.) The actual difference would probably be replacing LOAD_ATTR with LOAD_MUTATE_ATTR, Which would call __getmutatemethod__ instead of __getmethod__. (or something similar to that, depending on how it's implemented.)
> Why? There's no need for LOAD_MUTATE_ATTR. And LOAD_ATTR calls
> __getattribute__ (and __getattr__ if necessary), a bound method is a
> form callable attribute, the bytecode for a method call (assuming an
> object on the stack) is
>
> LOAD_ATTR $attrname
> CALL_FUNCTION
>
> that the function mutates the original object (or not) has no relevance
> to attribute loading.
Turn it around... If an object doesn't have a mutate-attribute-loader..
Then you will get an error before the CALL_FUNCION instead of during it or
after it, without making any changes to existing method/function call code
paths.
> > def names(defaults, pos_names, pos_args, kwds):
> > return {}.update(defaults) \
> > .update(zip(pos_names, pos_args)) \
> > .update(kwds)
> >
>>>> > >>> dis(names)
> > 2 0 BUILD_MAP 0
> > 3 LOAD_ATTR 0 (update)
> > 6 LOAD_FAST 0 (defaults)
> > 9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
> > 12 LOAD_ATTR 0 (update)
> >
> > 3 15 LOAD_GLOBAL 1 (zip)
> > 18 LOAD_FAST 1 (pos_names)
> > 21 LOAD_FAST 2 (pos_args)
> > 24 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
> > 27 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
> > 30 LOAD_ATTR 0 (update)
> >
> > 4 33 LOAD_FAST 3 (kwds)
> > 36 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
> > 39 RETURN_VALUE
> That bytecode's not correct for the case:
> * the return value of each method call needs to be discarded with a
> POP_TOP
> * LOAD_ATTR needs an object on the stack so you need a DUP_TOP before
> each LOAD_ATTR (update) (you can create the correct bytecode with
> something like byteplay, it'll work)
Actually, for it to work the way I was thinking, it needs a matched pair to
replace LOAD_ATTR and CALL_FUNCTION. The alternate call function bytecode
would leave the funciton on the stack and give an error if the returned
anything other than None. But I think that's too many new Byte codes. Even
one new byte code is a hard sell.
The idea is really just a more limited version of cascading with an error
for non-mutatables used with that syntax, and am error if any value is
returned when using with that syntax. So if you see this particular syntax
you will know instantly the intent is to mutate the subject.
It might be a fun patch to play with and/or try to do. But I don't think
it would ever get approved. The alternative is to use the existing byte
codes as you describe and that removes any (however small they might be)
performance benifits.
Cheers,
Ron
More information about the Python-ideas
mailing list