Python中的EagerMap

bvjxkvbb  于 2023-03-20  发布在  Python
关注(0)|答案(1)|浏览(54)

在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中性能最好的实现是什么。

odopli94

odopli941#

调用list(map(...))(如第一个示例中所示)就足以满足您的需要,甚至不需要另一个函数来 Package 它-因为它的意图很明显。
在这种情况下,使用列表和解析的性能差异应该是最小的,但是列表方面有优势,因为不需要执行Python VM操作--列表构建器将直接在本机代码中调用Map迭代器中的__next__。对于Pypy来说,这是不可预测的,因为对于足够长的有意义的序列,JIT将被触发,并且它可能有自己的方式。(无论如何,差异应该不相关)
现在,有时候,在Map函数执行I/O或有其他副作用的情况下,您可能只想应用map,而 * 不 * 存储结果。在这种情况下,最佳性能的方法几乎没有记录:maxlen为0的collections.deque结构实际上在内部进行了优化,以使用迭代器中的所有项,并处理所有项:

from collections import deque

...

deque(map(function, items), maxlen=0)  # <- process everyone and throws away the return values.

相关问题