[英]Python 2 vs 3: Replace list comprehensions with map()?
Given the following test: 进行以下测试:
>>> import timeit
>>> timeit.timeit("[x + 'abc' for x in ['x', 'y', 'z']]")
>>> timeit.timeit("map(lambda x: x + 'abc', ['x', 'y', 'z'])")
With Python 2.7 and 3.4 (Debian 8/testing/jessie) I get the following numbers: 使用Python 2.7和3.4(Debian 8 / testing / jessie),我得到以下数字:
Python27 Python34
1.3s 0.5s map()
0.6s 0.9s list comprehension
Map improved significantly with Python 3, the list comprehension suffered badly. 使用Python 3可使Map显着改善,列表理解受到严重影响。
Question: When porting code from Python 2 to Python 3, is it recommended to change list comprehensions to map()? 问题:将代码从Python 2移植到Python 3时,建议将列表理解更改为map()吗?
You are not testing correctly. 您没有正确测试。 In Python 3,
map()
returns an iterator, not a list. 在Python 3中,
map()
返回一个迭代器,而不是列表。 You are not actually iterating in your test, only testing the creation of the iterator. 您实际上并没有在测试中进行迭代,而只是在测试迭代器的创建。
You'll need to include iteration to see which approach is faster; 您需要包括迭代以查看哪种方法更快。 you could use
collections.deque()
with a length of 0, this will iterate without producing a new list object: 您可以使用长度为0的
collections.deque()
,这将在不产生新列表对象的情况下进行迭代:
import timeit
timeit.timeit("deque([x + 'abc' for x in ['x', 'y', 'z']], maxlen=0)",
'from collections import deque')
timeit.timeit("deque(map(lambda x: x + 'abc', ['x', 'y', 'z']), maxlen=0)",
'from collections import deque')
By applying the deque()
to both you even out the score again. 通过将
deque()
应用于两者,您可以再次使分数均匀。
Now list comprehensions win on both platforms: 现在,列表理解将在两个平台上均获胜:
Python27 Python34
1.91s 2.00s map()
1.18s 1.85s list comprehension
You should really use far larger input lists to properly test the differences; 您实际上应该使用更大的输入列表来正确测试差异。 too much o
太多
The reason list comprehensions slowed down on Python 3 is because they got their own proper scope, just like generator expressions and dict and set comprehensions do on both Python 2 and 3. 原因列表理解在Python 3上放慢的原因是,它们具有自己的适当范围,就像生成器表达式和dict和set理解在Python 2和3上一样。
If your map function is entirely implemented in C (as opposed to a lambda, which pushes back to Python, map()
could win: 如果您的地图函数完全用C实现(而不是lambda,后者会推回Python,则
map()
可能会获胜:
>>> timeit.timeit("deque([m(i) for i in ['x', 'y', 'z']], maxlen=0)",
... "from collections import deque; from operator import methodcaller; m = methodcaller('__add__', 'abc')")
2.3514049489967874
>>> timeit.timeit("deque(map(methodcaller('__add__', 'abc'), ['x', 'y', 'z']), maxlen=0)",
... 'from collections import deque; from operator import methodcaller')
1.7684289459939464
Here the methodcaller()
object avoids calling back into Python code by calling the str.__add__
method for each object used. 在这里,
methodcaller()
对象通过为每个使用的对象调用str.__add__
方法来避免回调Python代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.