Python 3与Python 2映射行为

the*_*olf 19 python python-3.x map-function

在Python 2中,一个常见的(旧的,遗留的)习惯用于使用map如下形式连接不均匀长度的迭代器map(None,iter,iter,...):

>>> map(None,xrange(5),xrange(10,12))
[(0, 10), (1, 11), (2, None), (3, None), (4, None)]
Run Code Online (Sandbox Code Playgroud)

在Python 2中,它被扩展,以便最长的迭代器是返回列表的长度,如果一个比另一个短,则用它填充None.

在Python 3中,这是不同的.首先,你不能None用作位置1中可调用的参数:

>>> list(map(None, range(5),range(10,12)))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable
Run Code Online (Sandbox Code Playgroud)

好的 - 我可以解决这个问题:

>>> def f(*x): return x    
... 
>>> list(map(f, *(range(5),range(10,12))))
[(0, 10), (1, 11)]
Run Code Online (Sandbox Code Playgroud)

但现在,我有一个不同的问题:map返回最短迭代器的长度 - 不再填充None.

当我将Python 2代码移植到Python 3时,这不是一个非常罕见的习惯用法,我还没有找到一个简单易用的解决方案.

不幸的是,2to3的工具,挑这件事-帮倒忙提示:

-map(None,xrange(5),xrange(10,18))
+list(map(None,list(range(5)),list(range(10,18)))) 
Run Code Online (Sandbox Code Playgroud)

建议?


编辑

有一些讨论这个成语有多常见.看到这篇SO帖子.

我正在更新我还在高中时写的遗留代码.看看Raymond Hettinger 编写和讨论的2003 Python教程,指出了这个特定的地图行为......

Dou*_*gal 18

itertools.zip_longest以更易于理解的名义做你想做的事.:)

  • @andrewcooke嗯,取决于你是否真的需要一个列表或只是想迭代它.... (4认同)
  • 确切地说,在Python 2.x中它被称为[`itertools.izip_longest()`](http://docs.python.org/library/itertools.html#itertools.izip_longest),因此没有必要这样做. map(无,*(iter,iter))`.+1 (3认同)

the*_*olf 2

这次我会回答我自己的问题。

对于 Python 3x,您可以像这样使用itertools.zip_longest :

>>> list(map(lambda *a: a,*zip(*itertools.zip_longest(range(5),range(10,17)))))
[(0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (None, 15), (None, 16)]
Run Code Online (Sandbox Code Playgroud)

我想你也可以自己推出:

>>> def oldMapNone(*ells):
...     '''replace for map(None, ....), invalid in 3.0 :-( '''
...     lgst = max([len(e) for e in ells])
...     return list(zip(* [list(e) + [None] * (lgst - len(e)) for e in ells]))
... 
>>> oldMapNone(range(5),range(10,12),range(30,38))
[(0, 10, 30), (1, 11, 31), (2, None, 32), (3, None, 33), (4, None, 34), (None, None, 35), (None, None, 36), (None, None, 37)]
Run Code Online (Sandbox Code Playgroud)

  • 我不明白你的答案的复杂性。以下内容是否有效: list(itertools.zip_longest(range(5),range(10,17))) (6认同)