Python:列表理解与地图

zen*_*poy 11 python performance

参考这个Python列表理解与.地图问题,有人可以解释为什么List Comprehensions map在列表理解不调用函数时会给出更好的结果,即使在没有lambda函数map但是在调用函数时给出最差的结果时?

import timeit

print timeit.Timer('''[i**2 for i in xrange(100)]''').timeit(number = 100000)

print timeit.Timer('''map(lambda i: i**2, xrange(100))''').timeit(number = 100000)

print timeit.Timer(setup="""def my_pow(i):
    return i**2
""",stmt="""map(my_pow, xrange(100))""").timeit(number = 100000)

print timeit.Timer(setup="""def my_pow(i):
    return i**2
""",stmt='''[my_pow(i) for i in xrange(100)]''').timeit(number = 100000)
Run Code Online (Sandbox Code Playgroud)

结果:

1.03697046805 <-- list comprehension without function call
1.96599485313 <-- map with lambda function
1.92951520483 <-- map with function call
2.23419570042 <-- list comprehension with function call
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 13

您的所有计时结果都可以通过以下事实来解释:

  1. CPython具有相当高的函数调用开销.

  2. map(f, it)比...快一点[f(x) for x in it].

您的代码的第一个版本根本没有定义函数,因此没有函数调用开销.第二个版本需要定义一个函数,因此每次迭代都有函数调用开销.第三个版本完全等同于第二个版本 - 函数和lambda表达式是相同的.根据事实2,最后一个版本甚至更慢.

  • 事实上我可以想到两个可能的原因(2):`map`的循环直接在C中发生,因此循环中的开销略微减少,而名称`f`的引用只需要解析一次` map`但是在列表理解的每次迭代中.第二种感觉对我来说更重要,但任何方式来分辨哪一个贡献更多? (3认同)