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