58

この記事は最終更新日から5年以上が経過しています。

投稿日

更新日

Organization

Pythonにてコールバック関数を使う

コールバック関数って?

コールバック関数とは、プログラム中で、呼び出し先の関数の実行中に実行されるように、あらかじめ指定しておく関数。
http://e-words.jp/w/%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E9%96%A2%E6%95%B0.html

関数の引数として渡す関数とも説明されることもあります。

使用方法

リンク先の記事まんまです
http://qiita.com/pocket8137/items/df5afba90b51e90587a5
まずはコールバック関数を呼び出す関数を定義。

def handler(func,*args):
    return func(*args)

第一引数が関数ポインタ、第二引数が可変引数です。第二引数にてコールバック関数の引数を受け取ります。

そして、コールバック関数を定義

def say_hello(name):
    print("Hello!!")
    print(name)

呼び出します。
ちなみに、Pythonでは関数名に()をつけないことで関数ポインタを指します。

if __name__ == "__main__":
    callback = say_hello
    #callbackにsay_helloのオブジェクトIDを格納
  handler(callback, "moroku0519")

実行結果

   Hello!!
   moroku0519

どういったことに使ったか

私の場合、場合によって使用する関数を分けたいなと思う場面がありました。
そこで、オブジェクトIDを格納した辞書を定義しました。

def handler(func, *args):
    return func(*args)

def function1(hoge):
    return hoge

def function2(hoge, huga):
    return hoge, huga

func_dic = {"func1": function1, "func2": function2}
result1 = handler(func_dic["func1"], hoge)
result2, result3 = handler(func_dic["func2"], hoge, huga)

新規登録して、もっと便利にQiitaを使ってみよう

  1. あなたにマッチした記事をお届けします
  2. 便利な情報をあとで効率的に読み返せます
ログインすると使える機能について
hatt0519
Android開発しています。
mixi
1997年の創業以来、SNS「mixi」やスマホアプリ「モンスターストライク」等、友人や家族といった親しい人と楽しむコミュニケーションサービスを提供してきました。これからも皆さまの生活をより豊かにすべく、新たな市場の創造に挑戦し続けます。 ※2022年10月1日、「株式会社ミクシィ」から「株式会社MIXI」へ商号が変わりました。

コメント

(編集済み)

pythonには「関数ポインタ」はなくて、関数だろうとインスタンスだろうと数値だろうとすべてオブジェクトで「オブジェクトID」が割り当てられていて、オブジェクトIDが辞書に登録されます。
オブジェクトIDはid関数で調べられ、オブジェクトが何者かはtypeコマンドで調べられます。
()を付けると__call__メソッドを呼び出すことになり、関数だけでなくlambda関数やクラスやメソッドも呼び出せます。__call__メソッドを持たない数値などはエラーになりますけど。

>>> id(function1)
43568112
>>> id(function2)
43568176
>>> id(func_dict["func1"])
43568112
>>> id(func_dict["func2"])
43568176
>>> type(function1)
<type 'function'>
>>> type(func_dict["func1"])
<type 'function'>
>>> type(123)
<type 'int'>
>>> id(123)
37845144
>>> 123()

Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    123()
TypeError: 'int' object is not callable

intのサブクラスを作って無理やり数値を関数呼び出しすることも可能ではあります。

>>> class myint(int): pass
... 
>>> a = myint(123)
>>> a
123
>>> a + 456
579
>>> a()

Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    a()
TypeError: 'myint' object is not callable
>>> myint.__call__ = lambda self: 'I am %s!' % self
>>> a()
'I am 123!'
7
(編集済み)

丁寧なご説明ありがとうございます!

2
(編集済み)

便利な記事をありがとうございます!引数がなくてもhandlerから実行できました!

def handler(func, *args):
    return func(*args)

def function1(hoge):
    return hoge

def function2(hoge, huga):
    return hoge, huga

def function3():
    return 0

func_dic = {"func1": function1, "func2": function2, "func3": function3}

hoge=1
huga=2
result1 = handler(func_dic["func1"], hoge)
print(result1)
result2, result3 = handler(func_dic["func2"], hoge, huga)
print(result2, result3)
result4 = handler(func_dic["func3"])
print(result4)
$ python test.py 
1
1 2
0
0
あなたもコメントしてみませんか :)
新規登録
すでにアカウントを持っている方はログイン
58