Python:是否在列表理解中对split函数进行了多次评估? [英] Python: Is the split function evaluated multiple times in a list comprehension?

查看:119
本文介绍了Python:是否在列表理解中对split函数进行了多次评估?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有些事情我一直想知道.在此列表理解中,拆分是执行一次还是多次?

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.

列表显示文档中:

在这种情况下,新列表的元素是通过将每个forif子句视为一个块,从左向右嵌套,并计算要生成的表达式而产生的元素每次到达最里面的块时都会使用一个列表元素.

In this case, the elements of the new list are those that would be produced by considering each of the for or if 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 lineLOAD_ATTR splitCALL_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆