Python はじめました:functools.reduce

Python.use(better) # Python はじめました記事一覧
functools.reduce

《著》小粒ちゃん+α《監修》小泉ひよ子とタマゴ倶楽部
第0版♪2001/03/02 ● 第1版♪2003/05/25 ● 第2版♪2004/06/01 ● 第3版♪2009/02/28

functools.reduce〈Python 3.0 版〉

関数 reduce を利用すると(情報隠蔽の原則に沿って)簡潔で見通しの良いコードを記述できるようになります。まず、その効能を確認するために、reduce を使わない事例を紹介します。

■ 事例:伝統的な手法
def fact1(n):
    acc = 1
    while n>1:
        print(n,"<<<")
        acc *= n
        n -= 1
    return acc

fact1 では、while に続く条件式 n>1 を満たす間は、ブロック内のコードを繰り返し評価します。変数 acc は、累積した値を保持します。

def fact2(n):
    acc = 1
    for e in range(n,1,-1):
        print(e,"<<<")
        acc *= e
    return acc

fact2 では、for に続く制御変数 e が、引数 n から 2 までの値を順に参照しながら、ブロック内のコードを繰り返し評価します。数 acc は、累積した値を保持します。

def fact3(n):
    if not n>1: return 1
    print(n,"<<<")
    return n*fact3(n-1)

fact3 では、if に続く条件式 not n>1 を満たすなら、再帰呼び出し fact3(n-1) によって、累積した値をリターン値として保持します。

■ 事例:reduce を用いた手法
from functools import reduce
def fact(n):
    return reduce(lambda acc,e:acc*e, range(n,1,-1), 1)

def ex():
    for e in range(6):
        s = "fact({0})".format(e)
        print(">>>",s)
        print(eval(s))        

% python3.0 -i ex30.py 
>>> ex()
>>> fact(0)
1
>>> fact(1)
1
>>> fact(2)
2
>>> fact(3)
6
>>> fact(4)
24
>>> fact(5)
120

for 文とともにジェネレータ g を利用すると、フィボナッチ数 e が順に得られます。

組み込み関数 reduce〈Python 2.x 版〉

Python 3.0 版〉と同様です。ただし、Python3.0 では(組み込み関数ではなく)モジュール functools を取り入れる必要があります。

def fact(n):
    return reduce(lambda acc,e:acc*e, range(n,1,-1), 1)

def ex():
    for e in range(6):
        s = "fact(%s)"%e
        print ">>>",s
        print eval(s)

% python2.6 -i ex26.py 
>>> ex()
>>> fact(0)
1
>>> fact(1)
1
>>> fact(2)
2
>>> fact(3)
6
>>> fact(4)
24
>>> fact(5)
120

Last updated♪09/03/12