filter, map和reduce在python2中完美地工作。这里有一个例子:
>>> 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
如果有人能给我解释一下这是为什么,我会很感激。
为进一步清晰起见,代码截图如下:
映射、过滤和还原的优点之一是,当你把它们“链接”在一起做一些复杂的事情时,它们变得多么容易读懂。但是,内置语法不清晰,而且都是“向后”的。因此,我建议使用PyFunctional包(https://pypi.org/project/PyFunctional/)。
以下是两者的对比:
flight_destinations_dict = {'NY': {'London', 'Rome'}, 'Berlin': {'NY'}}
PyFunctional版本
非常清晰的语法。你可以说:
“我有一系列的航班目的地。我想从中脱身
如果city在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())
)
)
from functools import reduce
def f(x):
return x % 2 != 0 and x % 3 != 0
print(*filter(f, range(2, 25)))
#[5, 7, 11, 13, 17, 19, 23]
def cube(x):
return x**3
print(*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
它是这样工作的。要获得map的输出,请使用*或list
map和filter的功能被有意地更改为返回迭代器,reduce从内置函数中删除并放在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%的情况下比reduce更容易读,但我还是坚持使用functools。reduce。
编辑:99%的数据直接来自Guido van Rossum撰写的“Python 3.0新增功能”页面。
映射、过滤和还原的优点之一是,当你把它们“链接”在一起做一些复杂的事情时,它们变得多么容易读懂。但是,内置语法不清晰,而且都是“向后”的。因此,我建议使用PyFunctional包(https://pypi.org/project/PyFunctional/)。
以下是两者的对比:
flight_destinations_dict = {'NY': {'London', 'Rome'}, 'Berlin': {'NY'}}
PyFunctional版本
非常清晰的语法。你可以说:
“我有一系列的航班目的地。我想从中脱身
如果city在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())
)
)