问题描述
在 Python 2 中,一个常见的(旧的、遗留的)习惯用法是使用 map
以 map(None,iter,iter,...)
像这样:
在 Python 2 中,它被扩展为 最长 迭代器是返回列表的长度,如果一个比另一个短,则用 None
填充.
在 Python 3 中,这是不同的.首先,您不能使用 None
作为位置 1 中可调用对象的参数:
好的——我可以这样解决:
>>>def f(*x): 返回 x...>>>列表(地图(f,*(范围(5),范围(10,12))))[(0, 10), (1, 11)]但是现在,我遇到了一个不同的问题:map
返回最短 迭代器的长度——不再填充 None
.
当我将 Python 2 代码移植到 Python 3 时,这并不是一个可怕的罕见习语,我还没有想出一个简单的就地解决方案.
不幸的是,2to3 工具没有选择这个-- 无益的建议:
-map(None,xrange(5),xrange(10,18))+列表(地图(无,列表(范围(5)),列表(范围(10,18))))
建议?
编辑
有一些关于这个习语有多普遍的讨论.请参阅此 SO 帖子.
我正在更新我还在高中时编写的遗留代码.看看 2003 年的 Python 教程是 由 Raymond Hettinger 撰写和讨论,并指出了地图的这种特定行为......
这次我会回答我自己的问题.
使用 Python 3x,您可以使用 itertools.zip_longest 像这样:
>>>列表(地图(lambda *a:a,* zip(*itertools.zip_longest(范围(5),范围(10,17)))))[(0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (None, 15), (None, 16)]我想你也可以推出自己的:
>>>def oldMapNone(*ells):... '''replace for map(None, ....), 在 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), (无,无,36),(无,无,37)]In Python 2, a common (old, legacy) idiom is to use map
to join iterators of uneven length using the form map(None,iter,iter,...)
like so:
>>> map(None,xrange(5),xrange(10,12))
[(0, 10), (1, 11), (2, None), (3, None), (4, None)]
In Python 2, it is extended so that the longest iterator is the length of the returned list and if one is shorter than the other it is padded with None
.
In Python 3, this is different. First, you cannot use None
as an argument for the callable in position 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
OK -- I can fix that like so:
>>> def f(*x): return x
...
>>> list(map(f, *(range(5),range(10,12))))
[(0, 10), (1, 11)]
But now, I have a different problem: map
returns the shortest iterator's length -- no longer padded with None
.
As I port Python 2 code to Python 3, this is not a terrible rare idiom and I have not figured out an easy in place solution.
Unfortunately, the 2to3 tools does not pick this up -- unhelpfully suggesting:
-map(None,xrange(5),xrange(10,18))
+list(map(None,list(range(5)),list(range(10,18))))
Suggestions?
Edit
There is some discussion of how common this idiom is. See this SO post.
I am updating legacy code written when I was still in high school. Look at the 2003 Python tutorials being written and discussed by Raymond Hettinger with this specific behavior of map being pointed out...
I'll answer my own question this time.
With Python 3x, you can use itertools.zip_longest like so:
>>> 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)]
You can also roll ur own I suppose:
>>> 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)]
这篇关于Python 3 与 Python 2 地图行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!