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 :(得分:299)
您可以在What's New In Python 3.0中了解更改。当你从2.x移动到3.x以来,你应该彻底阅读它,因为已经改变了很多。
这里的全部答案都是文档中的引用。
<强> Views And Iterators Instead Of Lists 强>
一些众所周知的API不再返回列表:
<强> Builtins 强>
- [...]
- 已移除
reduce()
。如果你确实需要,请使用functools.reduce()
;但是,99%的时间显式for
循环更具可读性。- [...]
答案 1 :(得分:77)
有意更改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%的时间比简化更容易阅读,但我只是坚持使用functools.reduce
。
修改:99%的数字是直接从Guido van Rossum撰写的What’s New In Python 3.0页面中提取的。
答案 2 :(得分:10)
作为其他答案的附录,这对于上下文管理器来说是一个很好的用例,它会将这些函数的名称重新映射到返回列表并在全局名称空间中引入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 :(得分:4)
由于已经从Python3的内置函数中删除了reduce
方法,所以请不要忘记在代码中导入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 :(得分:3)
map,filter和reduce的优点之一是当您将它们“链接”在一起以进行复杂的操作时,它们变得清晰易读。但是,内置语法不清晰,全都是“向后的”。因此,我建议使用PyFunctional
软件包(https://pypi.org/project/PyFunctional/)。
以下是两者的比较:
flight_destinations_dict = {'NY': {'London', 'Rome'}, 'Berlin': {'NY'}}
PyFunctional版本
语法非常清晰。你可以说:
“我有一系列的飞行目的地。我想从中获得 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())
)
)
答案 5 :(得分:0)
以下是Filter,map和reduce函数的示例。
数字= [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]
//过滤器
oddNumbers = list(filter(lambda x:x%2!= 0,数字))
打印(单数)
//地图
multiplyOf2 = list(map(lambda x:x * 2,数字))
print(multiplyOf2)
//减少
reduce函数由于不常用,已从Python 3的内置函数中删除。它仍在functools模块中可用,因此您可以执行以下操作:
从functools导入reduce
sumOfNumbers = reduce(lambda x,y:x + y,数字)
print(sumOfNumbers)
答案 6 :(得分:0)
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
它按原样工作。要获取地图的输出,请使用*或列表
答案 7 :(得分:0)
试着理解普通的 def 定义函数和 lambda 函数之间的区别。这是一个返回给定值的立方体的程序:
# Python code to illustrate cube of a number
# showing difference between def() and lambda().
def cube(y):
return y*y*y
lambda_cube = lambda y: y*y*y
# using the normally
# defined function
print(cube(5))
# using the lamda function
print(lambda_cube(5))
输出:
125
125
不使用 Lambda:
使用 Lambda:
Lambda 函数可以与 filter()
、map()
和 reduce()
等内置函数一起使用。
Python 中的 filter()
函数接受一个函数和一个列表作为参数。这提供了一种优雅的方法来过滤掉序列“序列”的所有元素,函数返回 True
。
my_list = [1, 5, 4, 6, 8, 11, 3, 12]
new_list = list(filter(lambda x: (x%2 == 0) , my_list))
print(new_list)
ages = [13, 90, 17, 59, 21, 60, 5]
adults = list(filter(lambda age: age>18, ages))
print(adults) # above 18 yrs
输出:
[4, 6, 8, 12]
[90, 59, 21, 60]
Python 中的 map()
函数接受一个函数和一个列表作为参数。使用 lambda 函数和一个列表调用该函数,并返回一个新列表,其中包含该函数为每个项目返回的所有 lambda 修改项。
my_list = [1, 5, 4, 6, 8, 11, 3, 12]
new_list = list(map(lambda x: x * 2 , my_list))
print(new_list)
cities = ['novi sad', 'ljubljana', 'london', 'new york', 'paris']
# change all city names
# to upper case and return the same
uppered_cities = list(map(lambda city: str.upper(city), cities))
print(uppered_cities)
输出:
[2, 10, 8, 12, 16, 22, 6, 24]
['NOVI SAD', 'LJUBLJANA', 'LONDON', 'NEW YORK', 'PARIS']
reduce()
的工作方式与 map()
和 filter()
不同。它不会根据我们传递的 function
和可迭代对象返回新列表。相反,它返回一个值。
此外,在 Python 3 中,reduce()
不再是内置函数,它可以在 functools
模块中找到。
语法是:
reduce(function, sequence[, initial])
reduce()
的工作原理是调用我们为序列中的前两项传递的 function
。 function
返回的结果与下一个(在本例中为第三个)元素一起用于对 function
的另一个调用。
可选参数 initial
出现在此“循环”的开头,第一次调用 function
时的第一个元素。在某种程度上,initial
元素是第 0 个元素,在第一个元素之前(如果提供)。
Python 中的 reduce() 函数接受一个函数和一个列表作为参数。使用 lambda 函数和可迭代函数调用该函数,并返回一个新的缩减结果。这对可迭代的对执行重复操作。
from functools import reduce
my_list = [1, 1, 2, 3, 5, 8, 13, 21, 34]
sum = reduce((lambda x, y: x + y), my_list)
print(sum) # sum of a list
print("With an initial value: " + str(reduce(lambda x, y: x + y, my_list, 100)))
88
With an initial value: 188
这些函数是方便函数。它们在那里,因此您可以避免编写更繁琐的代码,但避免同时使用它们和 lambda 表达式,因为“您可以”,因为它通常会导致难以维护的难以辨认的代码。仅当您在查看函数或 lambda 表达式后就完全清楚发生了什么时才使用它们。