如何在Python 3中使用filter,映射和减less

filtermap ,并reduce在Python 2完美的工作。这里是一个例子:

 >>> def f(x): return x % 2 != 0 and x % 3 != 0 >>> filter(f, range(2, 25)) [5, 7, 11, 13, 17, 19, 23] >>> def cube(x): return x*x*x >>> map(cube, range(1, 11)) [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000] >>> def add(x,y): return x+y >>> reduce(add, range(1, 11)) 55 

但在Python 3中,我收到以下输出:

 >>> filter(f, range(2, 25)) <filter object at 0x0000000002C14908> >>> map(cube, range(1, 11)) <map object at 0x0000000002C82B70> >>> reduce(add, range(1, 11)) Traceback (most recent call last): File "<pyshell#8>", line 1, in <module> reduce(add, range(1, 11)) NameError: name 'reduce' is not defined 

如果有人能向我解释为什么,我将不胜感激。

进一步清晰的代码屏幕截图:

Python 2和3的IDLE会话并排

您可以阅读关于Python 3.0新增function的更改。 当你从2.x移动到3.x时,你应该仔细阅读,因为很多已经改变了。

这里的整个答案都是来自文档的引用。

视图和迭代器而不是列表

一些众所周知的API不再返回列表:

  • […]
  • map()filter()返回迭代器。 如果你真的需要一个列表,一个快速修复是例如list(map(...)) ,但更好的解决scheme往往是使用列表理解(特别是当原始代码使用lambda),或重写代码,所以它不根本不需要一个清单。 特别棘手的是map()调用函数的副作用; 正确的转换是使用一个常规for循环(因为创build一个列表将是浪费)。
  • […]

内置命令

  • […]
  • 删除了reduce() 。 使用functools.reduce()如果你真的需要它; 但是,显式循环的99%时间更具可读性。
  • […]

mapfilter的function被有意改变,以返回迭代器,减less从内置和删除functools.reduce被删除。

因此,对于filtermap ,您可以用list()来包装它们,以便像以前那样查看结果。

 >>> def f(x): return x % 2 != 0 and x % 3 != 0 ... >>> list(filter(f, range(2, 25))) [5, 7, 11, 13, 17, 19, 23] >>> def cube(x): return x*x*x ... >>> list(map(cube, range(1, 11))) [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000] >>> import functools >>> def add(x,y): return x+y ... >>> functools.reduce(add, range(1, 11)) 55 >>> 

现在的build议是,您可以用生成器expression式或列表parsing来replace您对map和filter的使用。 例:

 >>> def f(x): return x % 2 != 0 and x % 3 != 0 ... >>> [i for i in range(2, 25) if f(i)] [5, 7, 11, 13, 17, 19, 23] >>> def cube(x): return x*x*x ... >>> [cube(i) for i in range(1, 11)] [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000] >>> 

他们说,for循环99%的时间比阅读更容易阅读,但我只是坚持functools.reduce

编辑 :百分之九十九的数字直接从Guido van Rossum所着的“Python 3.0新增function”页面中拉取。

作为其他答案的附录,这听起来像是一个上下文pipe理器的好用例,它将把这些函数的名称重新映射到返回一个列表并在全局名称空间中引入reduce的元素。

快速实施可能如下所示:

 from contextlib import contextmanager @contextmanager def noiters(*funcs): if not funcs: funcs = [map, filter, zip] # etc from functools import reduce globals()[reduce.__name__] = reduce for func in funcs: globals()[func.__name__] = lambda *ar, func = func, **kwar: list(func(*ar, **kwar)) try: yield finally: del globals()[reduce.__name__] for func in funcs: globals()[func.__name__] = func 

使用如下所示:

 with noiters(map): from operator import add print(reduce(add, range(1, 20))) print(map(int, ['1', '2'])) 

打印:

 190 [1, 2] 

只是我2美分:-)