这是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
字符串
据我所知,它创建了一个名为listcomp
的代码对象,它执行实际的迭代并返回结果列表,并立即调用它。我不明白为什么需要创建一个单独的函数来执行这个任务。这是一种优化技巧吗?
1条答案
按热度按时间kjthegm61#
创建函数的主要逻辑是isolate the comprehension’s iteration variablepeps.python.org。
创建一个函数:
理解迭代变量保持隔离,不会覆盖外部作用域中同名的变量,也不会在理解之后可见
但是它 * 在运行时效率很低 *。正因为如此,python-3.12实现了一个称为理解内联(PEP 709)的优化peps.python.org,它将不再创建单独的代码objectpeps.python.org。
字典、列表和集合解析现在是内联的,而不是为每次执行解析都创建一个新的一次性函数对象。这使执行解析的速度提高了两倍。有关详细信息,请参阅PEP 709。
下面是用python-3.12反汇编的相同代码的输出。
字符串
正如你所看到的,不再有
MAKE_FUNCTION
操作码。这将导致PEP 709如何为理解变量提供隔离的问题。嗯,这是通过使用LOAD_FAST_AND_CLEAR
(偏移量为6
)和STORE_FAST
(偏移量为30
)操作码来完成的。引用PEP 709的 Specification sectionpeps.python.org:x
迭代变量的隔离是通过在偏移量6
处组合新的LOAD_FAST_AND_CLEAR
操作码来实现的,该操作码在运行解析之前将x
的任何外部值保存在堆栈上,而30
STORE_FAST
在运行解析之后恢复x
的外部值(如果有的话)。这里是基准resultspeps.python.org(用MacOS M2测量)。
型