web-dev-qa-db-ja.com

Python 3でのfilter、map、およびreduceの使い方

filtermap、および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

誰かが私にこれがなぜなのか説明できれば幸いです。

より明確にするためのコードのスクリーンショット:

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

266
Dick Lucas

変更点については、 Python 3.0の新機能 を参照してください。たくさん変更されているので、2.xから3.xに移動するときは、それをよく読んでください。

ここに全体の答えはドキュメントからの引用です。

リストではなくビューとイテレータ

いくつかの有名なAPIはもはやリストを返しません:

  • [...]
  • map() および filter() はイテレータを返します。あなたが本当にリストを必要とするならば、迅速な修正は例えばです。 list(map(...))ですが、もっと良い修正方法はリストの内包表記を使うか(特にオリジナルのコードがlambdaを使うとき)、あるいはリストを必要としないようにコードを書き直すことです。特に厄介なのは、関数の副作用のために呼び出されるmap()です。正しい変換は、通常のforループを使うことです(リストを作成するのは無駄になるからです)。
  • [...]

ビルトイン

  • [...]
  • reduce()を削除しました。本当に必要な場合は functools.reduce() を使用してください。しかし、99パーセントの明示的なforループは読みやすくなっています。
  • [...]
297
nhahtdh

mapfilterの機能はイテレータを返すように意図的に変更され、reduceは組み込みから削除されてfunctools.reduceに配置されました。

そのため、filtermapについては、それらを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 and 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ループはreduceよりも99%読みやすいと言っていますが、私はfunctools.reduceを固執するだけです。

編集 :99%の数字は、Guido van Rossumが執筆した Python 3.0の新機能 から直接引用されています。

77
Joshua D. Boyd

他の答えの補足として、これはコンテキストマネージャがこれらの関数の名前をリストを返し、グローバル名前空間に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セント:-)

reduceメソッドはPython3の組み込み関数から削除されたので、コードに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
Bikash Singh

これは、フィルタ、マップ、リデュース関数の例です。

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

//フィルタ

oddNumbers = list(フィルタ(λx:x%2!= 0、数字))

印刷(奇数)

//地図

multiplyOf2 = list(map(λx:x * 2、number))

print(multiplyOf2)

//減らす

Reduce関数は、一般的には使用されていないので、Python 3の組み込み関数から削除されました。それでもfunctoolsモジュールで利用可能です。

functoolsのインポートから減らす

sumOfNumbers = reduce(λx、y:x + y、数)

print(sumOfNumbers)

0
Yogendra Singh