#はじめに
このポストでは、いくつかの外部モジュールから複数の関数を取り出し、それぞれのモジュール関数を同一ループ処理することを目指します。
#使い方
・同一のデータセットに対し、異なる算術関数を適用し比較したい場合
・複数サイトのクローリングなど、アクセス先は違うが内部処理は同じ場合など
#参考url
コールバック関数とは
Pythonにてコールバック関数を使う
##コールバック関数とは
コールバック関数とは他の関数に引数として渡す関数のこと。
基本は、
- ハンドラーを定義
- コールバック関数を定義
- 関数ポインタにコールバック関数を代入
- 関数ポインタをハンドラーの引数として渡す
#コールバック関数の使い方
まずhandlerという,関数を呼び出すための関数を定義します。
def handler(func,*args):
return func(*args)
次に引数として使いたい関数を定義します。
def double(x):
return x*x
最後にhandlerを使って上の関数を呼び出します。
k = 5
call = handler(double,k)
print(call)
>>>25
主な使い方としては、変数をlambda式で書ききれない場合にコールバック関数を使用する感じでしょうか。
#本題
さて、コールバック関数の使い方は分かりました。これを使って複数の関数を処理してみましょう。
まず、いくつかの関数が定義された外部モジュールhoge.pyを定義します。
def add(x):
return x+1
def sub(x):
return x-1
def mul(x):
return x*1
def div(x):
return x/1
次に、このhoge.pyをメインモジュールにインポートし、関数のリストとして定義します。
import hoge
func = [hoge.add, hoge.sub, hoge.mul, hoge.div]
pythonはすべてがオブジェクトと言う通り、関数も配列として格納できます。
もちろん、このまま使うこともできます。
func[0](1)
>>>2
func[1](1)
>>>0
それでは、メイン関数を定義していきましょう。
関数を呼び出すhandler関数と、それを使ったmath関数を定義します。
import hoge
func = [hoge.add, hoge.sub, hoge.mul, hoge.div]
#ハンドラーの定義
def handler(function, *arguments):
return function(*arguments)
#四則演算関数mathの定義
def math(lists):
def add(x):
return handler(lists[0], x)
def sub(x):
return handler(lists[1], x)
def mul(x):
return handler(lists[2], x)
def div(x):
return handler(lists[3], x)
return add, sub, mul, div
def main(x):
#関数の定義
add,sub,mul,div = math(func)
#それぞれの関数の和
sum = add(x)+sub(x)+mul(x)+div(x)
return sum
handler関数は任意の関数を引数にとり、その戻り値を返す関数でした。
math関数はfuncリストから関数を受け取り、新しい関数名として出力する関数です。
つまり、
add, sub, mul, div = math(func)
とした時、
add(x) == hoge.add(x)
sub(x) == hoge.sub(x)
mul(x) == hoge.mul(x)
div(x) == hoge.div(x)
という関係が成り立ちます。
main関数ではそれらの関数にxを代入したときの和を計算しています。
#本題の本題
こんなことをしてなんの意味があるのでしょうか?
ここで、新たな外部モジュールfuga.pyを定義します。
def add(x):
return x+2
def sub(x):
return x-2
def mul(x):
return x*2
def div(x):
return x/2
hoge.pyとfuga.pyはよく似ていますが、それぞれ違う関数です。これをメインモジュールにインポートします。
import hoge
import fuga
#辞書型に変更
funcs = {'hoge':[hoge.add, hoge.sub, hoge.mul, hoge.div],
'fuga':[fuga.add, fuga.sub, fuga.mul, fuga.div],
}
#ハンドラーの定義
def handler(function, *arguments):
return function(*arguments)
#四則演算関数mathの定義
def math(lists):
def add(x):
return handler(lists[0], x)
def sub(x):
return handler(lists[1], x)
def mul(x):
return handler(lists[2], x)
def div(x):
return handler(lists[3], x)
return add, sub, mul, div
#辞書のリストごとに関数を実行する
def main(x):
calc_list = []
for lists in funcs.values():
add,sub,mul,div = math(lists)
sum = add(x)+sub(x)+mul(x)+div(x)
calc_list.append(sum)
return calc_list
わかりやすいようにfuncsという辞書型リストを作成しました。これによって、外部モジュールそれぞれの関数がfuncsに格納されました。
また、main関数を一部変更し、外部モジュールそれぞれの関数リストからmath関数を呼び出せるようにfor文で囲み、ループ処理の結果を配列として出力するようにしました。
以上のような書き方をすることで、hoge.pyとfuga.pyからそれぞれ異なる関数を読み込み、main関数内で同一ループ処理することが可能になりました!
#実行結果
実行結果は以下になります!
for i in range(10):
print(main(i))
>>>'''
[0.0, 0.0]
[4.0, 4.5]
[8.0, 9.0]
[12.0, 13.5]
[16.0, 18.0]
[20.0, 22.5]
[24.0, 27.0]
[28.0, 31.5]
[32.0, 36.0]
[36.0, 40.5]
'''
2つの外部関数の結果を一度で比較することができました!
#おわりに
新たに外部関数を定義したら辞書にポンポン追加していくだけでmain関数を拡張できるのがこの手法のいいところだと思います。
コールバック関数の勉強にもなりました。
ここまで読んで頂きありがとうございました。