removing list comprehensions in Python 3.0
Steven Bethard
steven.bethard at gmail.com
Tue Jul 12 14:06:54 EDT 2005
Steven Bethard wrote:
> py> def ge(items):
> ... return (item for item in items if item)
> ...
Bengt Richter wrote:
> >>> dis.dis(ge)
> 2 0 LOAD_CONST 1 (<code object <generator expression> at 02EE4FA0, file "<stdin>", line 2>)
> 3 MAKE_FUNCTION 0
> 6 LOAD_FAST 0 (items)
> 9 GET_ITER
> 10 CALL_FUNCTION 1
> 13 RETURN_VALUE
[snip]
> >>> dis.dis(ge.func_code.co_consts[1])
> 2 0 SETUP_LOOP 28 (to 31)
> 3 LOAD_FAST 0 ([outmost-iterable])
> >> 6 FOR_ITER 21 (to 30)
> 9 STORE_FAST 1 (item)
> 12 LOAD_FAST 1 (item)
> 15 JUMP_IF_FALSE 8 (to 26)
> 18 POP_TOP
> 19 LOAD_FAST 1 (item)
> 22 YIELD_VALUE
> 23 JUMP_ABSOLUTE 6
> >> 26 POP_TOP
> 27 JUMP_ABSOLUTE 6
> >> 30 POP_BLOCK
> >> 31 LOAD_CONST 0 (None)
> 34 RETURN_VALUE
Outstanding. Thanks a lot! For comparison, here's the relevant dis.dis
output for list comprehensions.
py> def lc(items):
... return [item for item in items if item]
...
py> dis.dis(lc)
2 0 BUILD_LIST 0
3 DUP_TOP
4 STORE_FAST 1 (_[1])
7 LOAD_FAST 0 (items)
10 GET_ITER
>> 11 FOR_ITER 24 (to 38)
14 STORE_FAST 2 (item)
17 LOAD_FAST 2 (item)
20 JUMP_IF_FALSE 11 (to 34)
23 POP_TOP
24 LOAD_FAST 1 (_[1])
27 LOAD_FAST 2 (item)
30 LIST_APPEND
31 JUMP_ABSOLUTE 11
>> 34 POP_TOP
35 JUMP_ABSOLUTE 11
>> 38 DELETE_FAST 1 (_[1])
41 RETURN_VALUE
Interestingly, the LC code and the code of a GE's "generator-expression"
code object look quite similar, with basically a LOAD_FAST/LIST_APPEND
replaced by a YIELD_VALUE.
But I don't know byte code well enough to guess how the dangling local
variable in LCs will be eliminated in Python 3.0 (as has been suggested
a number of times). One way to eliminate it would be (as suggested) to
make LCs syntactic sugar for list(<genexp>). But it also looks like it
might be possible to do a DELETE_FAST with an appropriately hidden name...
STeVe
More information about the Python-list
mailing list