为什么map在Python 3中返回地图对象而不是列表?

NoI*_*his 73 python python-3.x

我有兴趣了解Python 3.x新语言设计.

我喜欢在Python 2.7中使用的功能map:

Python 2.7.12
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: [2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

但是,在Python 3.x中,事情发生了变化:

Python 3.5.1
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: <map at 0x4218390>
Run Code Online (Sandbox Code Playgroud)

我理解如何,但我找不到为什么的参考.为什么语言设计师会做出这样的选择,在我看来,这会引入很多痛苦.这是为了让开发人员坚持列表理解吗?

IMO,list自然可以被认为是Functors ; 而且我一直被认为以这种方式思考:

fmap :: (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

Rem*_*ich 32

我想,为什么地图仍然存在的原因发电机表情也是存在的,是它可以采取多个迭代论点,都环绕在并传递给函数:

>>> list(map(min, [1,2,3,4], [0,10,0,10]))
[0,2,0,4]
Run Code Online (Sandbox Code Playgroud)

这比使用zip稍微容易一些:

>>> list(min(x, y) for x, y in zip([1,2,3,4], [0,10,0,10]))
Run Code Online (Sandbox Code Playgroud)

否则,它根本不会在生成器表达式上添加任何内容.

  • 如果两个列表的长度不相等*,则在Python 2和3*中生成不同的结果.在python 2和python 3中尝试`c = list(map(max,[1,2,3,4],[0,10,0,10,99]))`. (2认同)

vis*_*ell 21

因为它返回一个迭代器,所以省略了将完整大小的列表存储在内存中.因此,您可以在将来轻松迭代它,而不会给记忆带来任何痛苦.可能你甚至不需要一个完整的清单,但它的一部分,直到你的状况达到.

你可以发现这个文档很有用,迭代器很棒.

表示数据流的对象.重复调用迭代器的__next__()方法(或将其传递给内置函数next())返回流中的连续项.当没有更多数据可用时,StopIteration会引发异常.此时,迭代器对象已耗尽,并且对其__next__()方法的任何进一步调用StopIteration再次引发.迭代器需要有一个__iter__()返回迭代器对象本身的方法,因此每个迭代器也是可迭代的,并且可以在大多数接受其他迭代的地方使用.一个值得注意的例外是尝试多次迭代传递的代码.list每次将容器对象(例如a )传递给iter()函数或在for循环中使用它时,它都会生成一个全新的迭代器.使用迭代器尝试此操作只会返回上一次迭代过程中使用的相同耗尽的迭代器对象,使其看起来像一个空容器.


cda*_*rke 13

Guido 在这里回答这个问题:" 因为创建一个列表只会浪费 ".

他还说正确的转换是使用常规for循环.

map()从2 转换为3可能不仅仅是一个简单的例子list( ).圭多还说:

"如果输入序列的长度不相等,map()则会在序列中最短的序列处停止.为了与map()Python 2.x 完全兼容,还要将序列包装起来itertools.zip_longest(),例如:

map(func, *sequences)
Run Code Online (Sandbox Code Playgroud)

list(map(func, itertools.zip_longest(*sequences)))
Run Code Online (Sandbox Code Playgroud)

"

  • 用`zip_longest`进行的转换是错误的.你必须使用`itertools.starmap`来使它等效:`list(starmap(func,zip_longest(*sequences)))`.那是因为`zip_longest`产生元组,所以`func`会收到一个`n`-uple参数而不是`n`不同的参数,就像调用`map(func,*sequences)`时那样. (4认同)
  • Guido注释是针对function_的副作用而调用_`map()`,而不是作为仿函数使用. (2认同)

Chr*_*nds 11

在Python 3的许多功能(而不仅仅是map但是zip,range和其他人)返回一个迭代器,而不是完整的列表.您可能需要一个迭代器(例如,以避免将整个列表保存在内存中),或者您可能需要一个列表(例如,能够索引).

但是,我认为Python 3发生变化的关键原因是,尽管使用list(some_iterator)反向等价物将迭代器转换为列表是微不足道的,但是iter(some_list)没有达到预期的结果,因为完整列表已经构建并保存在内存中.

例如,在Python 3中list(range(n))工作得很好,因为构建range对象然后将其转换为列表的成本很低.但是,在Python 2 iter(range(n))中没有保存任何内存,因为完整列表是在构建range()迭代器之前构造的.

因此,在Python 2中,需要单独的函数来创建迭代器而不是列表,例如imapfor map(尽管它们不完全等效),xrangefor range,izipfor zip.相比之下,Python 3只需要一个函数,因为list()如果需要,调用会创建完整列表.