Python在列表理解期间如何执行?

时间:2013-03-13 01:58:49

标签: python

def thing(mode, data):
    return [
        item for item in data
        if {
            'large': lambda item: item > 100,
            'small': lambda item: item < 100,
        }[mode](item)
    ]

此列表推导生成lambda的字典,通过mode参数检索一个lambda,并将其应用于当前正在处理的列表项。我的问题是:这有什么性能特征?

在listcomp的每次迭代期间是否从头开始创建整个字典?或者它是创建一次并用于每个项目?

3 个答案:

答案 0 :(得分:3)

  

在listcomp的每次迭代中是否从头开始创建整个字典

是。

  

或是它被创建一次并用于每个项目?

没有


幸运的是,在这种情况下(以及我能想到的所有其他类似情况),提前构建字典很容易:

 d = {
        'large': lambda item: item > 100,
        'small': lambda item: item < 100,
      }
 return [item for item in data if d[mode](item)]

甚至,

func = {
        'large': lambda item: item > 100,
        'small': lambda item: item < 100,
        }[mode]
return [item for item in data if func(item)]

答案 1 :(得分:2)

我很确定这会导致整个字典从头开始为列表的每个元素创建。 python列表推导的基本语法如下,

[ E1 for ID in E2 if E3 ]

其中E1,E2和E3是表达式。当解释器开始评估列表理解时,E2被评估一次。对E2评估的集合的每个成员评估E1和E3。所以,是的。在你的问题中,每次都是从头开始构建字典,但你可以通过在列表理解之前声明字典来轻松解决这个问题。

答案 2 :(得分:1)

你的字典每个循环创建一次,使你的列表理解速度比你缓存字典的速度快两倍:

>>> %timeit thing1('small', [1, 2, 3, 4, 5, 6])
100000 loops, best of 3: 2.4 us per loop
>>> %timeit thing2('small', [1, 2, 3, 4, 5, 6])
1000000 loops, best of 3: 1.06 us per loop

thing1是您原来的功能。 thing2是:

d = {
    'large': lambda item: item > 100,
    'small': lambda item: item < 100,
}

def thing3(mode, data):
    return list(filter(d[mode], data))

filter(f, data)item for item in data if f(item)的简写。在Python 3中,它创建了一个迭代器,它只在迭代时过滤掉项目。