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

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

整个字典是否在 listcomp 的每次迭代期间从头开始创建?还是只创建一次并在每个项目上使用?

4

3 回答 3

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)]
于 2013-03-13T02:05:00.223 回答
2

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

[ E1 for ID in E2 if E3 ],

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

于 2013-03-13T02:06:11.797 回答
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 中,它创建了一个迭代器,它仅在您对其进行迭代时过滤掉项目。

于 2013-03-13T02:09:28.280 回答