pythonの小ネタです。
概要
- 引数にコールバック関数を渡す代わりにインスタンスメソッドを渡すと、そのままコールバックされるし、
self
も参照できる。
情報量はこの一文で全てです。あまりやる機会もなさそうですが、「やったらどうなるのかな」と思う方がいるかもしれないので試して書きます。
関数に関数を渡す
関数Aの引数として関数Bを渡して、関数Aの中から関数Bを呼ぶ。いわゆるコールバックですね。標準ライブラリでも沢山使われているのでお馴染みだと思います。
def func_caller(func):
"""関数を受け取って呼び出す関数"""
func('引数を渡します。')
def param_func(text):
"""func_callerから呼び出される関数"""
print(text)
# 関数に関数を引数で渡す
func_caller(param_func)
実行結果も何の変哲もない。
$ python funcparam.py
引数を渡します。
printする関数param_func
をfunc_caller
から呼び出すだけなので普通にprintされます。
関数にインスタンスのメソッドだけ渡す
今度はクラスのインスタンスの中からメソッド部分だけをコールバック関数の代わりに渡します。引数にインスタンスが含まれないのでメソッドのself
がどうなるのかちょっと見た感じでは気になる書き方です。
def func_caller(func):
"""関数を受け取って呼び出す関数(さっきと同じ)"""
func('引数を渡します。')
class ParamClass:
"""引数にするメソッドを持つクラス"""
def __init__(self, mytext) -> None:
"""インスタンス変数mytextを持つ"""
self.mytext = mytext
def param_method(self, text):
"""引数textとself.mytextを一緒に出力する"""
print(text, self.mytext)
# インスタンスを生成して、メソッドを引数にする
param_class = ParamClass('インスタンス変数も使えます。')
func_caller(param_class.param_method)
実行結果はこうなります。
$ python methodparam.py
引数を渡します。 インスタンス変数も使えます。
instance.method()
のような呼び出しと変わらずself
が渡されので、いつも通りに自由な操作が行えます。しかし、これを使ってコールバック内からself
を操作してインスタンスの状態を変更するのは混乱を招くのでやめたほうがいいでしょう。せめてself
の内容を参照する程度にとどめておくべきでしょう。1
少なくともpythonの標準ライブラリ内ではこんな使い方をしたいライブラリはほとんどなさそうに思えます。強いて言うなら、コールバック関数が何らかのファクトリとして動作するときにはちょっと検討してもいいかもしれません。2