简体   繁体   English

Python 2 vs 3:用map()替换列表推导吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM