高階関数について【Python】

pythonの高階関数の記事のアイキャッチPython

高階関数というのはWikipediaから引用すると以下のようなものらしいです

高階関数とは第一級関数をサポートしているプログラミング言語において少なくとも以下のうち1つを満たす関数である

・関数を引数に取る
・関数を返す

Wikipedia – 高階関数

つまり関数を引数に取るか、関数を返す関数のことなんですね

簡単な高階関数を実装してみる

試しにとても簡単な高階関数を作ってみましょう

このコードは
関数を受け取って実行する関数であるdo_functionを使ってsay_helloを実行しています

def do_function(func):
    func()

def say_hello():
    print('hello')

do_function(say_hello)
# hello

確かに高階関数の定義である”関数を引数に取る” を満たしているので、do_functionは高階関数になっていますよね

Pythonでよく使う高階関数

map

mapは第一引数に関数、第二引数にはイテラブル(リスト, タプル)を与えると
イテラブルの全ての要素に第一引数の関数を適用した値を返すイテレータを返してくれます

またabsは絶対値を返してくれる関数でこれも組み込み関数です

x = [ i for i in range(-5, 6)]
# [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]

for i in map(abs, x):
    print(i)

# 5
# 4
# 3
# 2
# 1
# 0
# 1
# 2
# 3
# 4
# 5

filter

filterは第一引数に関数、第二引数にイテラブル(リスト、タプル)を取り、イテラブルの要素に関数を適用した結果がTrueであれば、その要素を抽出します

実際に返すものはfilterオブジェクトですが、イテレータと同じように中身を取り出すことが可能です

x = [ i for i in range(-5, 6)]
# [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]

def isPositive(a):
    if a > 0:
        return True
    else:
        return False

for i in filter(isPositive, x):
    print(i)

# 1
# 2
# 3
# 4
# 5

reduce

reduceは要素を足していったり、かけていったりすることで、一つの値にしてくれます

reduceも第一引数に関数、第二引数にイテラブルを取りますが、前述のmap, filterと違い、関数は2つを引数に取るようなものである必要があります

例えばreduceを用いて総和を求めるならこんな感じになりますね

from functools import reduce

def add(a, b):
    return a+b

x = [ i for i in range(0,10)]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(reduce(add, x))
# 45

max

maxは最大値を返す関数ですが、keyに関数を渡すことで、その関数を適用後の値に対してmaxを適用します

あくまで適用後の値を基準にして最大値を見つけるだけであり、実際に返ってくるのは与えた要素のうちの一つです

x = [ i for i in range(-6, 6)]
# [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]

print(max(x))
# 5
print(max(x, key=abs))
# -6

sorted

sortedはソートしたリストを返すものですが、keyに関数を渡すことで、関数を適用した値を基準にしてソートしてくれます

あくまで適用後の値を基準にしてソートするだけであり、実際に返ってくるのは与えたリストが並べ替えられたものです

x = [ i for i in range(-6, 6)]
# [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]

print(sorted(x))
# [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
print(sorted(x, key=abs))
# [0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6]

lamdaを使ってスッキリ

高階関数に渡す関数は簡単なものが多いですが、とても簡単な関数をいちいち定義するのは面倒ですよね?

そこでlambda式(無名関数)を使えばスッキリさせることができるのです

lambdaはこんな感じで使います

lambda 引数: 返り値
lambda x, y: x+y # 足し算
lambda x: x**2 # 二乗

それではlamdaを用いて高階関数をお手軽に使ってみましょう

x = [ i for i in range(0, 10)]

print(list(map(lambda n: n**2, x)))
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

いかがでしょうか?

二乗するための関数をわざわざ定義する必要もなく、コードもスッキリしました

コメント