filtermapreduce在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


如果有人可以向我解释为什么,我将不胜感激。 br />

评论

简而言之,list不是唯一的数据类型。如果需要列表,请说要列表。但是在大多数情况下,您仍然想要其他东西。

#1 楼

您可以阅读Python 3.0的新增功能中的更改。从2.x升级到3.x之前,您应该仔细阅读它,因为已经做了很多更改。 >
一些著名的API不再返回列表:

[...]

map()filter()返回迭代器。如果您确实需要列表,可以快速解决。 list(map(...)),但是更好的解决方案通常是使用列表理解(尤其是当原始代码使用lambda时),或者重写代码以使其根本不需要列表。为函数的副作用而调用map()尤其棘手;正确的转换是使用常规for循环(因为创建列表只会浪费)。
[...]


构建器


已移除reduce()。如果确实需要,请使用functools.reduce()。但是,在99%的时间中,显式for循环的可读性更高。
[...]



评论


在世界各地增加list(map(...)行,并且可读。在这里,您想要什么-嵌套在十几种方式中?

– StephenBoesch
18-2-27在5:29



如果您在命令性上下文中工作,那么for循环可能是更易读的选项。但是,有充分的理由偏爱功能性上下文-并且从该上下文中返回以返回到过程可能非常丑陋。

– MatrixManAtYrService
18年6月27日在15:08

@javadba您确定在“流应用程序”中根本不需要添加列表调用吗?我认为“流式传输”的含义是“根本不创建任何列表;在继续下一个输入之前,请完全处理输入的每个元素”。

–灭顶之夜
18-10-5在2:19

我仍然无法理解可读性参数如何导致这种变化。如果出于性能原因,我可能会理解...

–港区
18年11月8日在12:44

“快速修复”(阅读:hack)是使用list(map ...),但请注意,“更好的修复”是使用列表理解,例如[mylist中x的Foo(x)]。这不会导致到处添加list(),长期来看可能会更好。 (@javadba仅供参考)

–垄断
19年11月13日在15:52

#2 楼

故意更改了mapfilter的功能以返回迭代器,并将reduce不再是内置的并放置在functools.reduce中。像以前一样查看结果。例如:

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


他们说for循环在99%的时间内比在简化时更容易阅读,但我只是坚持使用filter

编辑:99%的数字直接来自Guido van Rossum编写的“ Python 3.0的新功能”页面。

评论


您无需在列表推导中创建其他功能。只需将[i * i * i用于范围(1,11)中的i]

–萧
2014年7月22日,下午3:25

你是绝对正确的。我将函数保留在列表理解示例中,以使其看起来类似于过滤器/地图示例。

–约书亚·博伊德(Joshua D. Boyd)
2014年9月2日在18:52

i ** 3也等于i * i * i

–微风
16年1月17日在15:13



@Breezer实际上i ** 3会调用i .__ pow __(3)和i * i * i i .__ mul __(i).__ mul __(i)(或类似名称)。使用int并不重要,但是使用numpy数字/自定义类甚至可能产生不同的结果。

–同义词
16年3月18日在11:06

我注意到,每当我们听到“圭多做出X决定”时,疼痛都是可能的结果。这是一个很好的例子:list(list(list(..)))来完成python已经很冗长的操作。

– StephenBoesch
18-10-5在4:17

#3 楼

作为其他答案的补充,对于上下文管理器来说,这听起来像是一个很好的用例,它将重新映射这些函数的名称为返回列表的函数,并在全局名称空间中引入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美分:-)

评论


python作为一种语言是一团糟-但它具有出色的库:numpy,pandas,statsmodels和friends ..我一直在像您在此处展示的便利库那样来减轻本地语言的痛苦-但已经失去了精力并尽量不要偏离data.frame / datatable或xarray。但是为尝试而赞誉。

– StephenBoesch
18-10-5在4:22

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


#5 楼

map,filter和reduce的优点之一是当您将它们“链接”在一起以执行复杂的操作时,它们变得清晰易读。但是,内置语法不清晰,全都是“向后的”。因此,我建议使用PyFunctional软件包(https://pypi.org/project/PyFunctional/)。
这里是两者的比较:您可以说:


“我有一系列的飞行目的地。如果城市位于dict值中,我想从其中获得dict键。最后,过滤删除我在此过程中创建的空列表。“


flight_destinations_dict = {'NY': {'London', 'Rome'}, 'Berlin': {'NY'}}


默认的Python版本

。您需要说:


“好,所以有一个列表。我想从中过滤出空列表。为什么?
因为我首先得到dict键该城市位于dict值中。
哦,我要输入的列表是flight_destinations_dict。“

#6 楼

以下是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,数字))

print(oddNumbers)




//地图




multipleOf2 = list(map(lambda x:x * 2,数字))

print(multiplyOf2)




// Reduce

reduce函数,因为它是从Python 3的内置函数中删除了不常用的函数。在functools模块中它仍然可用,因此您可以执行以下操作:




从functools导入reduce

sumOfNumbers = reduce(lambda x,y:x + y,数字)

print(sumOfNumbers)




#7 楼

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

它按原样工作。要获取地图的输出,请使用*或list