您在这里比较苹果和桔子。range
是 只是一个懒惰的迭代。它是一个特定的对象,其内容满足特定的法律,该法律允许支持许多操作而无需在内存中实际构建巨大的序列。这是因为的第n个元素range
基本上只是start + n*step
(模stop
,符号等)
但是map
它 可以使用 任何 功能f
。特别是功能可能具有共享/全局状态,这已经失去了在map(f, something)[100]
不执行100个功能调用的情况下能够执行的任何机会。不这样做会破坏结果的 正确性 。
map
“懒惰”只是意味着它不会立即生成完整的结果列表,而是等待您要求下一个结果,然后再调用f
并产生它。这样可以避免在代码中生成不必要的列表,例如:
for x in map(f, iterable):
# do something with x
如果map
急切的话iterable
,执行循环将消耗两倍的内存,而懒惰map
的话,所需的唯一空间x
基本上是。
此外,它可以调用map
的 无限iterables 一样count()
。这显然导致程序永无休止地做某事,或者在某个时候您可以停止调查map
。渴望map
不能处理这种情况。
如果您想使用仅适用于纯功能并且允许随机访问的受限映射,则可以编写自己的类:
class PureMap:
def __init__(self, function, sequence):
self._f = function
self._sequence = sequence
def __iter__(self):
return map(self._f, self._sequence)
def __getitem__(self, i):
return self._f(self._sequence[i])
# etc.
但是,即使在这种情况下,您仍然会遇到一些问题:
如果sequence
实际上是iterable
,则要获取第n个元素,则必须消耗前n个元素。之后,您必须将它们作为序列存储在类中,以备将来使用。但这已经违反了整件事的目的,因为这样做PureMap(f, sequence)[1000]
需要您始终将1000
元素存储在内存中,
您要避免f
在同一元素上多次调用。这意味着您还必须跟踪已计算出哪个元素,而未计算出哪个元素。
可以实现所需目标的唯一情况如下:
当所有这些假设都满足时,您可以拥有一个“像range
”一样工作的地图对象。