Python3与Python2的映射行为

Python3与Python2的映射行为,python,python-3.x,map-function,Python,Python 3.x,Map Function,在Python2中,一个常见的习惯用法是使用map以map(None,iter,iter,…)的形式连接长度不均匀的迭代器,如下所示: >>> map(None,xrange(5),xrange(10,12)) [(0, 10), (1, 11), (2, None), (3, None), (4, None)] >>> list(map(lambda *a: a,*zip(*itertools.zip_longest(range(5),range(10,1

在Python2中,一个常见的习惯用法是使用
map
map(None,iter,iter,…)
的形式连接长度不均匀的迭代器,如下所示:

>>> map(None,xrange(5),xrange(10,12))
[(0, 10), (1, 11), (2, None), (3, None), (4, None)]
>>> 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)]
在Python2中,对其进行了扩展,使最长的迭代器是返回列表的长度,如果一个迭代器比另一个迭代器短,则用
None
填充

在Python3中,这是不同的。首先,不能将
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
但是现在,我有一个不同的问题:
map
返回最短的迭代器长度——不再填充
None

当我将Python2代码移植到Python3时,这并不是一个非常罕见的习惯用法,而且我还没有找到一个简单的就地解决方案

不幸的是,2to3工具发现了这一点——毫无帮助地建议:

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


编辑

有人讨论过这个成语有多普遍


我正在更新高中时编写的遗留代码。请看Raymond Hettinger正在编写的2003 Python教程,其中指出了映射的具体行为…

做了您想要做的事情,并使用了一个更易于理解的名称。:)

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

使用Python 3x,您可以像这样使用:

我想你也可以自己滚:

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

您可以这样解决问题:

列表(映射(λx,y:(x,y),[1,2,3,4,5],[6,7,8,9,10]))

单向如果您需要Python2中一些过时的功能,那么单向-自己编写。当然,它不是内置的功能,但至少它是某种东西

下面的代码段共有27行

#!/usr/bin/env python3

def fetch(sequence, index):
  return None if len(sequence) <= index else sequence[index]

def mymap(f, *args):
  max_len = 0
  for i in range(len(args)): 
      max_len = max(max_len, len(args[i]))
  out = []
  for i in range(max_len):
      t = []
      for j in range(len(args)): 
          t.append(fetch(args[j],i))      

      if f != None:
          # Use * for unpack arguments from Arbitarily argument list
          # Use ** for unpack arguments from Keyword argument list
          out.append(f(*t))
      else:
          out.append(tuple(t))
  return out 

if __name__ == '__main__':
    print(mymap(None, [1,2,3,4,5],[2,1,3,4],[3,4]))
    print(mymap(None,range(5),range(10,12)))
#/usr/bin/env蟒蛇3
def fetch(序列、索引):

如果len(sequence)
map(None,*(iter,iter))
不是常见的习惯用法,则返回None。你听说过吗?做的和你描述的完全一样,但没有噱头。@Tadeck:因为描述的行为
map
,是的,这并不少见…@drewk:我熟悉
map()
的工作原理,但在这种情况下使用
map(None,*(iter,iter))
对我来说似乎很不和谐。此外,我还想知道,为什么
map(无,*(xrange(5),xrange(10,12))
而不是更直接的
map(无,xrange(5),xrange(10,12))
?完全一样。有没有证据可以证明它是pythonic的?Guido的确认就足够了,或者Raymond Hettinger的,或者Python的部分文档就足够了;我说这很常见,因为这是Python 2中
map
中记录的行为。谷歌“不同长度的python连接列表”一些较旧的答案使用map;我以前肯定从未见过它。在任何情况下,这个功能都被
zip
zip\u longest
所取代,这在我看来更容易理解。确切地说,在Python2.x中调用了它,因此不需要做
map(None,*(iter,iter))
+1尽管如此,你仍然需要在其周围粘贴一个
list()
。@andrewcooke好吧,这取决于你是真的需要一个列表,还是只是想反复浏览一下……我不理解你答案的复杂性。以下内容是否有效:list(itertools.zip_longest(范围(5),范围(10,17)))
#!/usr/bin/env python3

def fetch(sequence, index):
  return None if len(sequence) <= index else sequence[index]

def mymap(f, *args):
  max_len = 0
  for i in range(len(args)): 
      max_len = max(max_len, len(args[i]))
  out = []
  for i in range(max_len):
      t = []
      for j in range(len(args)): 
          t.append(fetch(args[j],i))      

      if f != None:
          # Use * for unpack arguments from Arbitarily argument list
          # Use ** for unpack arguments from Keyword argument list
          out.append(f(*t))
      else:
          out.append(tuple(t))
  return out 

if __name__ == '__main__':
    print(mymap(None, [1,2,3,4,5],[2,1,3,4],[3,4]))
    print(mymap(None,range(5),range(10,12)))