#高階関数!!!!
全くわからないので、記事にすると同時に調べてみました。
#詰まったのはここらへんからです。
テキスト通り、ベクトルの計算をする関数を作っていきます
# 引数同士を足す関数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^)/