Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么一个iterable上的map返回一个one-shot iterable?_Python_Python 3.x_Iterator_Iteration - Fatal编程技术网

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库,它似乎满足了我的需要。