问题:如何在Python 3中使用过滤,映射和归约
filter
,,map
并且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
如果有人可以向我解释为什么,我将不胜感激。
代码的屏幕截图,用于进一步说明:
回答 0
您可以阅读Python 3.0的新增功能中的更改。从2.x升级到3.x时,应该仔细阅读它,因为已经做了很多更改。
此处的完整答案是文档中的引号。
一些著名的API不再返回列表:
- […]
- 已删除
reduce()
。functools.reduce()
如果确实需要,请使用;但是,在99%的时间里,显式for
循环更易于阅读。- […]
回答 1
的功能map
和filter
被有意改为返回迭代器,并减少从被除去的内置和放置在functools.reduce
。
因此,对于filter
和map
,您可以将它们包装起来以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
>>>
现在的建议是,用生成器表达式或列表推导替换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
。
编辑:99%的数字直接从Guido van Rossum编写的“ Python 3.0的新功能”页面中提取。
回答 2
作为其他答案的补充,对于上下文管理器来说,这听起来像是一个很好的用例,它将重新将这些函数的名称映射为返回列表并引入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美分:-)
回答 3
由于该reduce
方法已从Python3的内置函数中删除,因此请不要忘记functools
在您的代码中导入。请查看下面的代码段。
import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)
回答 4
以下是Filter,map和reduce函数的示例。
数字= [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]
//过滤
奇数=列表(filter(lambda x:x%2!= 0,数字))
打印(奇数)
//地图
multipleOf2 = list(map(lambda x:x * 2,数字))
打印(multiplyOf2)
//降低
由于不常用reduce函数,因此已从Python 3的内置函数中删除了它。functools模块中仍提供了reduce函数,因此您可以执行以下操作:
从functools进口减少
sumOfNumbers = reduce(lambda x,y:x + y,数字)
打印(sumOfNumbers)
回答 5
map,filter和reduce的优点之一是当您将它们“链接”在一起以进行复杂的操作时,它们变得清晰易读。但是,内置语法不清晰,全都是“向后的”。因此,我建议使用该PyFunctional
软件包(https://pypi.org/project/PyFunctional/)。
这是两者的比较:
flight_destinations_dict = {'NY': {'London', 'Rome'}, 'Berlin': {'NY'}}
Py功能版本
非常清晰的语法。你可以说:
“我有一个飞行目的地序列。如果城市位于dict值中,我想从中获得dict键。最后,过滤掉我在流程中创建的空列表。”
from functional import seq # PyFunctional package to allow easier syntax
def find_return_flights_PYFUNCTIONAL_SYNTAX(city, flight_destinations_dict):
return seq(flight_destinations_dict.items()) \
.map(lambda x: x[0] if city in x[1] else []) \
.filter(lambda x: x != []) \
默认Python版本
都是倒退。您需要说:
“好的,所以有一个列表。我想从中过滤出空列表。为什么?因为如果城市位于dict值中,我首先得到了dict键。哦,我要执行的列表是flight_destinations_dict。 ”
def find_return_flights_DEFAULT_SYNTAX(city, flight_destinations_dict):
return list(
filter(lambda x: x != [],
map(lambda x: x[0] if city in x[1] else [], flight_destinations_dict.items())
)
)