Python 3与Python 2地图行为

发布于 2021-01-29 17:52:14

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

>>> map(None,xrange(5),xrange(10,12))
[(0, 10), (1, 11), (2, None), (3, None), (4, None)]

在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

好的-我可以这样解决:

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

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

当我将Python 2代码移植到Python 3时,这不是一个可怕的罕见习语,而且我还没有找到一个简单的解决方案。

不幸的是,2to3工具无法解决问题-无益地建议:

-map(None,xrange(5),xrange(10,18))
+list(map(None,list(range(5)),list(range(10,18))))

有什么建议吗?


编辑

我正在更新 还在上高中时 编写的旧代码 看一下Raymond
Hettinger编写和讨论的2003
Python教程,指出地图的这种特定行为…

关注者
0
被浏览
49
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

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

    使用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)]
    

    我想你也可以自己动手:

    >>> 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)]
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看