在Python中,map
函数是惰性的,但我通常需要一个急切的Map。
例如,尝试切片贴图对象会导致错误:
>>>> map(abs, [3, -1, -4, 1])[1:]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'map' object is not subscriptable (key slice(1, None, None))
我想我需要自己实现一个eager map,所以我想知道在Python中是否有标准的方法来实现它。
我设法用几种不同的方式实现它,但我不确定哪种替代方案更好,我同时要求CPython和PyPy 3,如果答案因Python实现而异,我希望知道所有相关的选项。
这些是我的实现:
def eager_map_impl0(f, *collections):
return list(map(f, *collections))
def eager_map_impl1(f, *collections):
return [x for x in map(f, *collections)]
def eager_map_impl2(f, *collections):
return [*map(f, *collections)]
def eager_map_impl3(f, *collections):
return [f(*x) for x in zip(*collections)]
用法示例:
>>>> eager_map_impl0(abs, [3, -1, -4, 1])[1:]
[1, 4, 1]
>>>> eager_map_impl1(abs, [3, -1, -4, 1])[1:]
[1, 4, 1]
>>>> eager_map_impl2(abs, [3, -1, -4, 1])[1:]
[1, 4, 1]
>>>> eager_map_impl3(abs, [3, -1, -4, 1])[1:]
[1, 4, 1]
关于重复投票,链接的问题和它的一些答案很有趣,但我想这里不是答案,我已经知道我想使用map
,而不是列表解析;所以我希望有人能在这里回答CPython与Pypy中性能最好的实现是什么。
1条答案
按热度按时间odopli941#
调用
list(map(...))
(如第一个示例中所示)就足以满足您的需要,甚至不需要另一个函数来 Package 它-因为它的意图很明显。在这种情况下,使用列表和解析的性能差异应该是最小的,但是列表方面有优势,因为不需要执行Python VM操作--列表构建器将直接在本机代码中调用Map迭代器中的
__next__
。对于Pypy来说,这是不可预测的,因为对于足够长的有意义的序列,JIT将被触发,并且它可能有自己的方式。(无论如何,差异应该不相关)现在,有时候,在Map函数执行I/O或有其他副作用的情况下,您可能只想应用
map
,而 * 不 * 存储结果。在这种情况下,最佳性能的方法几乎没有记录:maxlen为0的collections.deque
结构实际上在内部进行了优化,以使用迭代器中的所有项,并处理所有项: