Raymond Hettinger <raymond.hettin...@gmail.com> added the comment: FYI, here is the disassembly of the inner code objects. It shows where the difference in speed arises:
>>> from dis import dis >>> def f(): lc = [i for i in [1, 2]] ge = (i for i in [1, 2]) return lc, ge >>> for obj in f.__code__.co_consts: if type(obj) == type(f.__code__): print(obj) dis(obj) <code object <listcomp> at 0x113d881e0, file "<pyshell#26>", line 2> 2 0 BUILD_LIST 0 2 LOAD_FAST 0 (.0) >> 4 FOR_ITER 8 (to 14) 6 STORE_FAST 1 (i) 8 LOAD_FAST 1 (i) 10 LIST_APPEND 2 <-- Append directly 12 JUMP_ABSOLUTE 4 >> 14 RETURN_VALUE <code object <genexpr> at 0x1035afe40, file "<pyshell#26>", line 3> 3 0 LOAD_FAST 0 (.0) >> 2 FOR_ITER 10 (to 14) 4 STORE_FAST 1 (i) 6 LOAD_FAST 1 (i) 8 YIELD_VALUE <-- Pass data through iterator 10 POP_TOP <-- Dispose of None from send() 12 JUMP_ABSOLUTE 2 >> 14 LOAD_CONST 0 (None) 16 RETURN_VALUE The list comprehension builds the list directly with the high-speed specialized, LIST_APPEND opcode. The generator runs YIELD_VALUE and POP_TOP but the work isn't done. There needs to be a context switch to list_extend() which then extract the value from the iterator and finally appends it to the list. Executive summary: there is overhead when passing data through the iterator protocol. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue32945> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com