Speed of Nested Functions & Lambda Expressions

Duncan Booth duncan.booth at invalid.invalid
Fri Dec 7 04:56:03 EST 2007


Terry Jones <terry at jon.es> wrote:

> Duncan Booth wrote:
> 
>> You can use Python's bytecode disassembler to see what actually gets 
>> executed here:
>> 
>> >>> def fn_outer(v):
>>     a=v*2
>>     def fn_inner():
>>         print "V:%d,%d" % (v,a)
>> 
>>     fn_inner()
>>     
>> >>> import dis
>> >>> dis.dis(fn_outer)
>>   2           0 LOAD_DEREF               1 (v)
> [snip]
[snip]
> 
> I'd like to understand what it is that triggers the use of
> LOAD/STORE_DEREF versus LOAD/STORE_FAST. This seems dependent on how
> fn_inner above uses the a and v variables. If I change the print
> "V:%d,%d" % (v,a) line to be something like (a, v) = (v, a) or do
> other simple uses and assignments to a and v, LOAD/STORE_FAST is used.
> It seems that it's the use of print (in this case) that triggers the
> use of LOAD/STORE_DEREF in the bytecode. 

> Can anyone shed more light on what in general causes the switch to
> LOAD/STORE_DEREF?

You'll kick yourself for not seeing it.

If you changed fn_inner to:

      def fn_inner():
          a, v = v, a

then you also changed 'a' and 'v' into local variables. LOAD/STORE_FAST is 
used to access local variables, LOAD/STORE_DEREF are used to access 
variables in an outer scope.

There is no way in Python 2.x to rebind a name from a nested scope: any 
name you use as a target of an assignment is always either a local variable 
or a global variable.

(Actually, that's a lie, Google some of my old posts if you want to know 
how to rebind a name in a nested scope, but I warn you in advance it is 
really hackish and not something you would ever do for real.)



More information about the Python-list mailing list