如何在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): …

问题：如何在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]

return x+y
>>> reduce(add, range(1, 11))
55
``````

``````>>> 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>
NameError: name 'reduce' is not defined
``````

`filter`, `map`, and `reduce` work perfectly in Python 2. Here is an example:

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

return x+y
>>> reduce(add, range(1, 11))
55
``````

But in Python 3, I receive the following outputs:

``````>>> 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>
NameError: name 'reduce' is not defined
``````

I would appreciate if someone could explain to me why this is.

Screenshot of code for further clarity:

回答 0

• [...]
• 返回迭代器。如果您确实需要列表，则可以使用快速解决方案，例如`list(map(...))`，但是更好的解决方案通常是使用列表理解（特别是当原始代码使用lambda时），或者重写代码以使其根本不需要列表。`map()`该函数的副作用特别棘手。正确的转换是使用常规`for`循环（因为创建列表将很浪费）。
• [...]

• [...]
• 已删除`reduce()``functools.reduce()`如果确实需要，请使用；但是，在99％的时间里，显式`for`循环更易于阅读。
• [...]

You can read about the changes in What's New In Python 3.0. You should read it thoroughly when you move from 2.x to 3.x since a lot has been changed.

The whole answer here are quotes from the documentation.

Views And Iterators Instead Of Lists

Some well-known APIs no longer return lists:

• [...]
• and return iterators. If you really need a list, a quick fix is e.g. `list(map(...))`, but a better fix is often to use a list comprehension (especially when the original code uses lambda), or rewriting the code so it doesn’t need a list at all. Particularly tricky is `map()` invoked for the side effects of the function; the correct transformation is to use a regular `for` loop (since creating a list would just be wasteful).
• [...]

Builtins

• [...]
• Removed `reduce()`. Use `functools.reduce()` if you really need it; however, 99 percent of the time an explicit `for` loop is more readable.
• [...]

回答 1

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

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

The functionality of `map` and `filter` was intentionally changed to return iterators, and reduce was removed from being a built-in and placed in `functools.reduce`.

So, for `filter` and `map`, you can wrap them with `list()` to see the results like you did before.

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

The recommendation now is that you replace your usage of map and filter with generators expressions or list comprehensions. Example:

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

They say that for loops are 99 percent of the time easier to read than reduce, but I'd just stick with `functools.reduce`.

Edit: The 99 percent figure is pulled directly from the What’s New In Python 3.0 page authored by Guido van Rossum.

回答 2

``````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(map(int, ['1', '2']))``````

``````190
[1, 2]``````

As an addendum to the other answers, this sounds like a fine use-case for a context manager that will re-map the names of these functions to ones which return a list and introduce `reduce` in the global namespace.

A quick implementation might look like this:

``````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 a usage that looks like this:

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

Which prints:

``````190
[1, 2]
``````

Just my 2 cents 🙂

回答 3

``````import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)``````

Since the `reduce` method has been removed from the built in function from Python3, don't forget to import the `functools` in your code. Please look at the code snippet below.

``````import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)
``````

回答 4

//过滤

//地图

multipleOf2 = list（map（lambda x：x * 2，数字））

//降低

sumOfNumbers = reduce（lambda x，y：x + y，数字）

Here are the examples of Filter, map and reduce functions.

numbers = [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]

//Filter

oddNumbers = list(filter(lambda x: x%2 != 0, numbers))

print(oddNumbers)

//Map

multiplyOf2 = list(map(lambda x: x*2, numbers))

print(multiplyOf2)

//Reduce

The reduce function, since it is not commonly used, was removed from the built-in functions in Python 3. It is still available in the functools module, so you can do:

from functools import reduce

sumOfNumbers = reduce(lambda x,y: x+y, numbers)

print(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 != []) \``````

“好的，所以有一个列表。我想从中过滤出空列表。为什么？因为如果城市位于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())
)
)``````

One of the advantages of map, filter and reduce is how legible they become when you "chain" them together to do something complex. However, the built-in syntax isn't legible and is all "backwards". So, I suggest using the `PyFunctional` package (https://pypi.org/project/PyFunctional/). Here's a comparison of the two:

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

PyFunctional version

Very legible syntax. You can say:

"I have a sequence of flight destinations. Out of which I want to get the dict key if city is in the dict values. Finally, filter out the empty lists I created in the process."

``````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 != []) \
``````

Default Python version

It's all backwards. You need to say:

"OK, so, there's a list. I want to filter empty lists out of it. Why? Because I first got the dict key if the city was in the dict values. Oh, the list I'm doing this to is 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())
)
)
``````