Python:是否在列表理解中对split函数进行了多次评估? [英] Python: Is the split function evaluated multiple times in a list comprehension?
问题描述
有些事情我一直想知道.在此列表理解中,拆分是执行一次还是多次?
There is something I've been wondering about for a while. Is the split executed once or multiple times in this list comprehension?
l = [line.split()[i] for i in indexes]
我目前确实以这种方式列出这样的理解:
I currently do list comprehensions like these in this way:
l = line.rstrip().split()
l = [l for i in indexes]
但是我不确定是否有必要.除了肯定/否定答案外,我肯定想知道,如何通过执行CPU性能分析或阅读一些文档来自己找到有关此问题的信息.谢谢.
But I'm not sure, whether it's necessary. In addition to a yes/no answer I would definitely like to know, how I could go about finding out about this myself by either by doing CPU profiling or reading some documentation. Thanks.
推荐答案
对列表元素左侧的表达式重新评估,是的.
The expression on the left in a list comprehension is evaluated anew for each element, yes.
如果您只需要对它进行一次评估,则需要完全按照自己的意愿进行;首先调用它,然后将结果存储在列表推导中.
If you only need it evaluated once, you need to do exactly what you did; call it first and store the result to be re-used in the list comprehension.
从 列表显示文档中:
在这种情况下,新列表的元素是通过将每个
for
或if
子句视为一个块,从左向右嵌套,并计算要生成的表达式而产生的元素每次到达最里面的块时都会使用一个列表元素.
In this case, the elements of the new list are those that would be produced by considering each of the
for
orif
clauses a block, nesting from left to right, and evaluating the expression to produce a list element each time the innermost block is reached.
强调我的.
您还可以使用 dis.dis()
函数<:
You could also disassemble the list comprehension using the dis.dis()
function:
>>> import dis
>>> dis.dis(compile('[line.split()[i] for i in indexes]', '', 'eval'))
1 0 BUILD_LIST 0
3 LOAD_NAME 0 (indexes)
6 GET_ITER
>> 7 FOR_ITER 22 (to 32)
10 STORE_NAME 1 (i)
13 LOAD_NAME 2 (line)
16 LOAD_ATTR 3 (split)
19 CALL_FUNCTION 0
22 LOAD_NAME 1 (i)
25 BINARY_SUBSCR
26 LIST_APPEND 2
29 JUMP_ABSOLUTE 7
>> 32 RETURN_VALUE
FOR_ITER
操作码开始循环(JUMP_ABSOLUTE
关闭循环),并且每次执行LOAD_NAME line
,LOAD_ATTR split
和CALL_FUNCTION
.换句话说,字节码13到19实现line.split()
部分,并且每次通过循环执行,该循环从字节码7到29运行.
The FOR_ITER
opcode starts the loop (with the JUMP_ABSOLUTE
closing it), and each time a LOAD_NAME line
, LOAD_ATTR split
and CALL_FUNCTION
are executed. In other words, the bytecodes 13 through to 19 implement the line.split()
part, and it is executed each time through the loop, which runs from bytecodes 7 through to 29.
(Python 3注:列表推导有其自身的作用域,您需要从外部代码对象常量中提取代码对象; dis.dis(compile('[line.split()[i] for i in indexes]', '', 'eval').co_consts[0])
).
(Python 3 note: list comprehensions got their own scope and you'll need to extract the code object from the outer code object constants; dis.dis(compile('[line.split()[i] for i in indexes]', '', 'eval').co_consts[0])
).
这篇关于Python:是否在列表理解中对split函数进行了多次评估?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!