Python 为什么一个iterable上的map返回一个one-shot iterable?
为什么用一个可以多次迭代的对象调用Python 为什么一个iterable上的map返回一个one-shot iterable?,python,python-3.x,iterator,iteration,Python,Python 3.x,Iterator,Iteration,为什么用一个可以多次迭代的对象调用map时,不返回一个也可以多次迭代的对象?我认为后者更为合理 我的用例是我有大量的数据,因此只能对其进行迭代map在理论上非常适合于对数据进行操作,因为它是惰性的。但是,在下面的示例中,我希望长度是相同的两倍 iterable = [1,2,3,4] # this can be iterated repeatedly m = map(lambda x:x**2, iterable) # this again should be iterable repeate
map
时,不返回一个也可以多次迭代的对象?我认为后者更为合理
我的用例是我有大量的数据
,因此只能对其进行迭代map
在理论上非常适合于对数据进行操作,因为它是惰性的。但是,在下面的示例中,我希望长度是相同的两倍
iterable = [1,2,3,4] # this can be iterated repeatedly
m = map(lambda x:x**2, iterable) # this again should be iterable repeatedly
print(len(list(m))) # 4
print(len(list(m))) # 0
我如何映射一个iterable结构并得到一个iterable结构
编辑:
这是一个it imho应该如何工作的示例,演示了惰性评估:
def g():
print('g() called')
data = [g, g]
# map is lazy, so nothing is called
m = map(lambda g: g(), data)
print('m: %s' % len(list(m))) # g() is called here
print('m: %s' % len(list(m))) # this should work, but doesnt
# this imap returns an iterable
class imap(object):
def __init__(self, fnc, iterable):
self.fnc = fnc
self.iterable = iterable
def __iter__(self):
return map(self.fnc, self.iterable)
# imap is lazy, so nothing is called
im = imap(lambda g: g(), data)
print('im: %s' % len(list(im))) # g() is called here
print('im: %s' % len(list(im))) # works as expected
为什么当使用可以多次迭代的对象调用map时,它不会返回也可以多次迭代的对象
因为没有接口来判断对象是否可以重复迭代map
无法判断它所迭代的对象是否支持重复迭代,除非map
设法以某种方式确定此信息并发明API将其公开给用户,map
用户将无法判断其map
对象是否支持重复迭代
此外,重复迭代需要重复函数求值或缓存结果(但是如果要缓存结果,为什么要重新设计map
以返回迭代器?)。重复的功能评估效率低下,存在潜在危险,通常不是用户想要的。如果用户想要再次迭代,最好让他们显式地重复map
调用或显式地调用list
如果map
对象始终只是迭代器,则更简单。如果需要使用len
,那么为什么不从列表理解开始呢?它同样懒惰,并且会产生永久的结果。如果您需要len
,但确实想使用map
,只需在map
的输入上调用len
,而不是在map
的输出上调用即可。如果您想能够重复地遍历它,为什么不使用列表呢?或者仅仅使用列表理解?例如,它可能会消耗太多内存。非常确定len
只是作为一个例子来说明它不能被消耗两次。为了澄清:x是iter(x)
可以用来确认iter是不可重复的,但是你。@ZeroPiraeus:问题中甚至有一个反例:问题本身的imap
类有x不是iter(x)
,但是只有在底层iterable支持的情况下才支持重复迭代。您的第二点是一个折衷方案,其他实现map的语言(Haskell、Java、Scala、Closoure等)都必须以某种方式面对和解决。我找到了PyFunctional库,它似乎满足了我的需要。