为什么map与izip_longest一样有fill = None?

Mik*_*rns 8 python zip dictionary

map具有不同长度的输入时,填充值None用于缺少的输入:

>>> x = [[1,2,3,4],[5,6]]
>>> map(lambda *x:x, *x)
[(1, 5), (2, 6), (3, None), (4, None)]
Run Code Online (Sandbox Code Playgroud)

这与以下行为相同:

>>> import itertools
>>> list(itertools.izip_longest(*x))
[(1, 5), (2, 6), (3, None), (4, None)]
Run Code Online (Sandbox Code Playgroud)

是什么原因导致map了这种行为,而不是以下情况?

>>> map(lambda *x:x, *x)
[(1, 5), (2, 6), (3,), (4,)]
Run Code Online (Sandbox Code Playgroud)

...并有一个简单的方法来获得后者的行为或者与一些味道zip还是map

Ash*_*ary 5

我认为这是核心开发人员在实施时选择的设计决策map.map当它与多个迭代一起使用时,没有普遍定义的行为,引用Map(高阶函数):

当列表具有不同长度时,具有2个或更多列表的映射遇到处理问题.各种语言不同; 一些引发异常,一些在最短列表的长度后停止并忽略其他列表中的额外项目; 一些继续到最长列表的长度,对于已经结束的列表,将一些占位符值传递给函数,指示没有值.

因此,Python核心开发人员在1993年选择None用作较短迭代的占位符,于1993年map被引入 Python.

但是,如果itertools.imap它的短路具有最短的可迭代性,因为它的设计受到标准ML,Haskell和APL等语言的大量启发.在标准ML和Haskell map以最短的可迭代结束(虽然我不确定APL).

Python 3还删除了map(None, ...)(或者我们应该说itertools.imap,Python 3 map实际上几乎就是itertools.imap:从中移动到map()itertoolsbuiltins)构造,因为它只存在于Python 2中,因为当时map已经添加到Python中,Python中没有zip()函数.

来自Issue2186:map并且filter不应该支持None作为第一个参数(仅在Py3k中):

我赞同Guido,map(None, ...)如果zip()存在的话 ,我们永远不会创造.主要用例已过时.


为了获得你想要的结果我建议使用itertools.izip_longestsentinel值(object())而不是默认值None,None如果iterables本身包含None:

from itertools import izip_longest


def solve(seq):
    sentinel = object()
    return [tuple(x for x in item if x is not sentinel) for item in 
            izip_longest(*seq, fillvalue=sentinel)]


print solve([[1,2,3,4],[5,6]])
# [(1, 5), (2, 6), (3,), (4,)] 
Run Code Online (Sandbox Code Playgroud)

  • 哦,你找到了更合适的引用+1 :)我过了一段时间就放弃了[问Tim](http://stackoverflow.com/questions/20320585/python-what-are-lambdas-for/20320604#comment48368640_20320604)如果他可以帮到这里:D (2认同)