LoginSignup
53
56

More than 5 years have passed since last update.

python3と高階関数

Last updated at Posted at 2017-11-25

高階関数!!!!

全くわからないので、記事にすると同時に調べてみました。

詰まったのはここらへんからです。

テキスト通り、ベクトルの計算をする関数を作っていきます


# 引数同士を足す関数add_something
def add_something(v,w):
    return [v_i+ w_i
            for v_i, w_i in zip(v,w)]


def sum_something(vectors):
    #対応する要素の総和
    result = vectors[0]
    for vector in vectors[1:]:
        result = add_something(result, vector)
    return vector

上の式はこのように書き直せるらしい


def sum_something(vectors):
    return reduce(vector_add, vector)

また、このようにも書き直せるらしい


sum_something = partial(reduce, vector_add)

むむむむむっ!更にわからない!

そもそも高階関数とは

この言葉がとても参考になりました。
高階関数を一言で表すと、「関数を引数、戻り値として扱う関数」のことです。
@may88seijiさん:【JavaScript 高階関数を説明するよ

今まで引数に変数、定数を使っていたけど、高階関数を使えば関数を引数とか戻り値に出来るんですね。

reduce,map,filterについても一気に覚える

この際一気に覚えようと思います!

1:map関数

map関数は各要素に対してやりたいことが出来るので、二倍にするプログラムを書きます。

まずは、mapを使わないで書いてみます。

the_list = [1,2,3,4]

def double(x):
    return x*2

print([double(i) for i in the_list])
#[2,4,6,8]

mapを使えば、このように書ける!


the_list = [1,2,3,4]

# TT押しとかではないです。
twice = map(lambda x:x*2, the_list)

print(twice)

#>>> <map object at 0x1029cdd68>
#>>> [2,4,6,8]と出てくるはず!

python2まではこの書き方でも出力されたそうですが、python3からは使用するメモリを減らすために、list関数に渡さないと表示されなくなりました。

そのため、このように書き直します。


the_list = [1,2,3,4]


twice = list(map(lambda x:x*2, the_list))

#または、
#def double(x): return x*2
#twice = list(map(double, the_list))

print(twice)
#>>> 無事[2,4,6,8]と出力されました。

lambdaもそうですが、doubleを渡しているときも関数を渡していますね。

2:filter関数

filterを使うと、条件に該当する値だけ取ってこれるそうです

普通に書く方法もやってみたかったのですが、条件から外れた値がNoneになってリストに入ってしまったので、誰かやり方をわかる方いましたら教えてくださいm(__)m

追記! @SatoshiTerasaki さんにおしえていただきけました!

filter関数を使わないと、こうなります!


arr=[i for i in range(16) if i%3==0]

print(arr)
#>>>[0, 3, 6, 9, 12, 15]

@SatoshiTerasaki さん、ありがとうございます(^^)!

filter関数を使うと


#ここでもリスト関数を使っていることに注意してください。
#第二引数にiを渡しているのもポイントかなと思います。

val = list(filter(lambda x: x % 3 == 0, range(16)))

print(val)
#>>>[0, 3, 6, 9, 12, 15]

便利ですね!!

3:reduce関数

reduce関数の特徴ですが、今までのように第一引数に関数を使えますが、第一引数に取る関数は引数が2つ無いといけないようです。

なぜなら、reduceが順番に([0]番目と[1]番目、[0と1]番目と[2]番目、[0と1と2]番目と[3]番目)処理する関数だから、2つの引数がある関数じゃないといけないのですね。

#ファイルの頭でimportする
from functools import reduce

the_list = [1,2,3,4]

#第1引数に持ってくる関数、squareは引数が2つ
def square(x,y):
    return x * y

ans = reduce(square, the_list)
print(ans)

reduce関数だけ他の高階関数と違うところが多かったので、まとめてみました!

1:返り値がリストや辞書等の方ではないので、list関数を使わなくて大丈夫!
2:第一引数に持ってくる関数は、引数が2つ!
3:functoolsからimportしないといけない!

ちなみに、引数が1つの関数を第一引数に持ってくると、このようなエラーが出ます。

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: square() takes 1 positional argument but 2 were given

ちゃんと知るタイミングを作れて良かったです。

partialってなんだろうか

wpのテーマとか、railsのviewファイルで使うパーシャルと多分仕組みは同じなのかなと思っていました。

調べてもあんまりわかりやすい説明がなかったんですが、多分、引数に関数を2つ取って、新しい関数を作れるメソッドなのかなと思っています。

#文頭でpartialを呼び出す。
from functools import partial, reduce

the_list = [1,2,3,4]

i = range(16)

def square(x,y):
    return x * y

def double(x):
    return x * 2

#mapの場合
map_func = partial(map, double)

print(list(map_func(the_list)))
#>>>[2, 4, 6, 8]


#filterの場合
filter_func = partial(filter,lambda x:x%3 == 0)

print(list(filter_func(i)))
#>>>[0, 3, 6, 9, 12, 15]


#reduceの場合
reduce_func = partial(reduce, square)

print(reduce_func(the_list)) 
#>>>24

こう見ると、partialもすごい便利ですね!partialにも使う上でポイントがあるなと思ったのでまとめます。

・functoolsからimportが必要になります!
・map関数とfilter関数の説明をした際は、関数を変数に代入する際にlist関数を使いましたが、partialを使う場合はprintする際にlist関数を使わないとエラーが出ちゃいます!
・さっきまではイテレーターでしたが、パーシャルはイテレーターではないようです!

list関数のエラー内容はこちらです!

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'functools.partial' object is not iterable

最後に

まだまだわからないことだらけですが、少しづつ分かってきているかなと思います!

filter関数の部分で、つまずいたところがわかる方がいたらおしえていただけると幸いです!

今回も見てくださった方ありがとうございました\(^o^)/

53
56
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
53
56