This is disassembly of a list comprehension in python-3.10:
Python 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> 
>>> dis.dis("[True for _ in ()]")
  1           0 LOAD_CONST               0 (<code object <listcomp> at 0x7fea68e0dc60, file "<dis>", line 1>)
              2 LOAD_CONST               1 ('<listcomp>')
              4 MAKE_FUNCTION            0
              6 LOAD_CONST               2 (())
              8 GET_ITER
             10 CALL_FUNCTION            1
             12 RETURN_VALUE
Disassembly of <code object <listcomp> at 0x7fea68e0dc60, file "<dis>", line 1>:
  1           0 BUILD_LIST               0
              2 LOAD_FAST                0 (.0)
        >>    4 FOR_ITER                 4 (to 14)
              6 STORE_FAST               1 (_)
              8 LOAD_CONST               0 (True)
             10 LIST_APPEND              2
             12 JUMP_ABSOLUTE            2 (to 4)
        >>   14 RETURN_VALUE
From what I understand it creates a code object called listcomp which does the actual iteration and return the result list, and immediately call it.
I can't figure out the need to create a separate function to execute this job. Is this kind of an optimization trick?
                        
The main logic of creating a function is to isolate the comprehension’s iteration variablepeps.python.org.
By creating a function:
However, this is inefficient at runtime. Due to this reason, python-3.12 implemented an optimization called comprehension inlining(PEP 709)peps.python.org which will no longer create a separate code objectpeps.python.org.
Here is the output for the same code disassembled with python-3.12:
As you can see, there is no longer a
MAKE_FUNCTIONopcode nor a separate code object. Instead python-3.12 usesLOAD_FAST_AND_CLEARdocs.python.org(at offset6) andSTORE_FAST(at offset30) opcodes to provide the isolation for the iteration variable.Quoting from the Specification sectionpeps.python.org of the PEP 709:
In addition to that, in python-3.12 there is no longer a separate frame for the comprehension in tracebacks.
And here is the benchmark resultspeps.python.org(measured with MacOS M2):