您在这里比较苹果和桔子。
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
元素存储在内存中, 即使它避免了对的999
调用f
。您要避免
f
在同一元素上多次调用。这意味着您还必须跟踪已计算出哪个元素,而未计算出哪个元素。
可以实现所需目标的唯一情况如下:
- 被调用的函数是纯函数
- 可迭代的参数类似于这样
range
,它允许随机访问而不必产生其他元素 - 您调用的函数很快,因此您可以在各种元素上重新计算它,而不必过多担心性能。
当所有这些假设都满足时,您可以拥有一个“像
range”一样工作的地图对象。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)