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
Post a Comment