python - Why does locals() return a strange self referential list? -


so i'm using locals() grab arguments in function. works nicely:

def my_function(a, b):     print locals().values()  >>> my_function(1,2) [1, 2] 

standard stuff. let's introduce list comprehension:

def my_function(a, b):     print [x x in locals().values()]  >>> my_function(1,2) [[...], 1, 2] 

ehh? why has inserted self-reference?

python versions before 2.7 , 3.1 used suboptimal bytecode produce list comprehension. in python versions, list comprehension stored in local variable (or global, if @ module scope):

>>> import dis >>> def foo(): ...     return [x x in y] ...  >>> dis.dis(foo)   2           0 build_list               0               3 dup_top                            4 store_fast               0 (_[1])               7 load_global              0 (y)              10 get_iter                     >>   11 for_iter                13 (to 27)              14 store_fast               1 (x)              17 load_fast                0 (_[1])              20 load_fast                1 (x)              23 list_append                       24 jump_absolute           11         >>   27 delete_fast              0 (_[1])              30 return_value         

the _[1] local variable list-in-progress. when nesting list comprehensions use increasing integers refer result:

>>> def bar(): ...     return [[x x in y] z in spam] ...  >>> dis.dis(bar)   2           0 build_list               0               3 dup_top                            4 store_fast               0 (_[1])               7 load_global              0 (spam)              10 get_iter                     >>   11 for_iter                40 (to 54)              14 store_fast               1 (z)              17 load_fast                0 (_[1])              20 build_list               0              23 dup_top                           24 store_fast               2 (_[2])              27 load_global              1 (y)              30 get_iter                     >>   31 for_iter                13 (to 47)              34 store_fast               3 (x)              37 load_fast                2 (_[2])              40 load_fast                3 (x)              43 list_append                       44 jump_absolute           31         >>   47 delete_fast              2 (_[2])              50 list_append                       51 jump_absolute           11         >>   54 delete_fast              0 (_[1])              57 return_value         

by looping on locals().values() included reference list-in-progress in return value. note bytecode uses delete_fast clean local name try , avoid namespace pollution.

this optimized python 3.1 , 2.7, see issue 2183. list result under construction moved stack instead. optimization changed list_append bytecode reference list on stack append to, removing need use dup_top -> store_fast @ start, load_fast each iteration , delete_fast after list comprehension.


Comments

Popular posts from this blog

Android layout hidden on keyboard show -

google app engine - 403 Forbidden POST - Flask WTForms -

c - Why would PK11_GenerateRandom() return an error -8023? -