reduce() の第一引数は引数を2つ取る関数、第二引数はコンテナ、となります。
以下は具体的な例です。
>>> from functools import reduce >>> from operator import mul >>> c = [1, 2, 3, 4, 5] >>> reduce(mul, c) 120上記 reduce() の中で実際に行われている処理は、以下のようになります。
コンテナの各要素を関数でまとめ上げる、といった感じですね。
mul(mul(mul(mul(1, 2), 3), 4), 5)
reduce() を使わない一般的なループ文は以下のようになります。
>>> m = 1 >>> for i in c: >>> m *= i >>> m 120同じ処理の実装に3行必要となっていますので、reduce() の方がスッキリとした実装であると言えます。
書き方以外にも、reduce() は c[0] から計算を始めているのに対し、一般的なループ文の例では1行目で m の初期化を行っている点も相違点です。
reduce() の第二引数のサイズが0の時、および1の時には、それぞれ以下のように動作します。特にサイズが0の場合は例外発生するので要注意です。
# サイズが0ならエラー >>> reduce(int.mul, []) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: reduce() of empty sequence with no initial value # サイズが1なら[0] >>> reduce(int.mul, [10]) 10
以下は reduce() のもう少し実践的な使用例です。文字列の XORチェックサムを求めています。
>>> from functools import reduce >>> from operator import xor >>> s = "ABC" >>> reduce(xor, (ord(i) for i in s)) 64
以下余談です。
Python 2 では高階関数として map(), filter(), reduce() の3つがビルトイン関数として用意されていました。
しかし、Python 3 では reduce() のみが functools へと移されました。ビルトインから別モジュールへの移動ですから、事実上の降格です。
私にはこの決定が良い物とは思えません。
と言うのも、map() および filter() は内包表記を使うことで、同等の処理を実現できます。仮に map() と filter() が降格になるならば、それは「Python は内包表記を推している」という風に受け取られると思います。
しかし reduce() にはこれと言った代替手段は無く、reduce() を使わないとなると普通にループ文を書くしかありません。代替手段の無い reduce() こそ、ビルトインに残る方が良いと思うのですが、、、。
降格の一番の理由は、Guido氏(Python の開発者)が reduce() を「直感的でない」と否定的に見ていることのようです。
0 件のコメント:
コメントを投稿