How to write Inline Functions in Python?

Bengt Richter bokr at oz.net
Mon Nov 18 15:18:04 EST 2002


On Mon, 18 Nov 2002 00:57:52 -0800, Brian Quinlan <brian at sweetapp.com> wrote:

>Michael Stenner wrote:
>> I feel like we're going around in circles here.  I'm talking about
>> python.  It looks like 'inline' would produce serious speedups in some
>> cases.  Therefore, it looks like an inline command would not be
>> useless.
>
>Doing this would be almost impossible because Python name binding is
>done at runtime. For example, how would you compile this?
>
True, binding is done at runtime, but ISTM an alternate binding mechanism is
conceivable. I.e., the purpose of inlining is typically to generate a code
sequence "in line" where the source is apparently calling the inline function,
binding what would otherwise be the parameter names in function body directly
to the arguments and avoiding the whole call rigamarole -- which is significant
overhead in Python.

The question is, what kind of object would a *compiled* inline function have to be
to be used in Python analogy to that? I.e., what if you had a mutable code body type,
where there would be mutable slots corresponding to places where function parameters
were referenced? Let's how that could be used in your examples...

>if random.choice([0, 1]):
>    from foo import baz # baz is an inline function
>else:
>    from bar import baz # baz is an inline function
>
Either way, baz would be a mutable code body with no parameter slots.

>
>def my_func():
>    baz()
my_func would just get the baz code body at def time. Note that inline
means global references if any go to the global name space of the my_func def environment.

>
>Or this?
>
>inline def foo():
>    ....
>
>inline def bar():
>    ....
>
>def my_func()
>    foo()
>    globals['foo'] = bar
>    foo()
at def-time, globals()['foo'] is not dynamically touched, so you get

def my_func()
    <foo body>
    globals()['foo'] = bar # I assume you meant the ()
    <foo body>

the result of a my_func() call would do whatever <foo body> implies, plus rebind
the global foo at run time to the inline bar mutable code object (which a subsequent
def could "call" and get inlined into itself).

>
>
>Or this?
>
>from bar import baz # baz is an inline function
>
baz would be bound to a mutable code body
>def my_func()
>    ....
>    return baz # the fact that baz is inline isn't known at compile time
>
my_func would just return the reference.


What's more interesting is

def(inline) times_ten(x):
    return x*10

then

    def my_func(y):
        return times_ten(y)

should get the body of times_ten with the reference to x changed to y
E.g., looking at current code:

 >>> def times_ten(x):
 ...     return x*10
 ...
 >>> dis.dis(times_ten)
           0 SET_LINENO               1

           3 SET_LINENO               2
 _______________________________________________    <<-- mutable code body
/                                               \  
           6 LOAD_FAST                0 (x)     |   <<--mutable code parameter slot x gets replaced
           9 LOAD_CONST               1 (10)    |
          12 BINARY_MULTIPLY                    |
\_______________________________________________/
          13 RETURN_VALUE
          14 LOAD_CONST               0 (None)
          17 RETURN_VALUE

 >>> def my_func(y):
 ...     return times_ten(y)
 ...
 >>> dis.dis(my_func)
           0 SET_LINENO               1

           3 SET_LINENO               2
 ____________________________________________________
/                                                    \ <<-- replaced at def time if times_ten
           6 LOAD_GLOBAL              0 (times_ten)  | <<-- is mutable code body at def time
           9 LOAD_FAST                0 (y)          | <<-- actual parameter y ref replaces (x)
          12 CALL_FUNCTION            1              | <    in mutable code slot when body is substituted
\____________________________________________________/
          15 RETURN_VALUE
          16 LOAD_CONST               0 (None)
          19 RETURN_VALUE

This is just HOTTOMH, but I think there is something there.
Note that this is not a source macro operation.

Regards,
Bengt Richter



More information about the Python-list mailing list