如何在Python 3中使用filter、map和reduce ?

[英]How to use filter, map, and reduce in Python 3


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

在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

But in Python 3, I receive the following outputs:

但是在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

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

如果有人能解釋一下為什么會這樣,我將不勝感激。

Screenshot of code for further clarity:

代碼的屏幕截圖進一步清晰:

IDLE sessions of Python 2 and 3 side-by-side

3 个解决方案

#1


241  

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.

您可以閱讀Python 3.0中的新內容的更改。當你從2開始的時候,你應該仔細閱讀它。x 3。因為很多東西都變了。

The whole answer here are quotes from the documentation.

這里的全部答案是來自文檔的引用。

Views And Iterators Instead Of Lists

視圖和迭代器而不是列表

Some well-known APIs no longer return lists:

一些著名的api不再返回列表:

  • [...]
  • […]
  • map() and filter() 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).
  • map()和filter()返回迭代器。如果您確實需要一個列表,那么一個快速修復就是list(map(…)),但是更好的解決方法通常是使用列表理解(特別是當原始代碼使用lambda),或者重寫代碼,這樣它就不需要列表了。特別棘手的是針對函數的副作用調用map();正確的轉換是使用一個常規的for循環(因為創建一個列表將是浪費)。
  • [...]
  • […]

Builtins

內置命令

  • [...]
  • […]
  • Removed reduce(). Use functools.reduce() if you really need it; however, 99 percent of the time an explicit for loop is more readable.
  • 減少()刪除。如果確實需要,可以使用function .reduce();然而,99%的情況下,一個顯式的for循環更加可讀。
  • [...]
  • […]

#2


62  

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.

map和filter的功能被有意地更改為返回迭代器,並且reduce被從內置的功能中刪除,並放置到function tools.reduce中。

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

因此,對於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
>>>

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

現在的建議是使用生成器表達式或列表理解替換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]
>>>

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

他們說for循環有99%的時間更容易閱讀而不是減少,但我還是堅持使用function工具。

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

編輯:99%的數字直接來自於由Guido van Rossum撰寫的Python 3.0頁面的新內容。

#3


5  

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.

作為對其他答案的補充,這聽起來像是上下文管理器的一個很好的用例,它將這些函數的名稱重新映射到返回列表並在全局名稱空間中引入reduce的函數。

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(reduce(add, range(1, 20)))
    print(map(int, ['1', '2']))

Which prints:

打印:

190
[1, 2]

Just my 2 cents :-)

就我的2分:-)


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2012/11/30/7127aafa4845dfc88981c5bba8d76682.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com