Pythonのコードリーディングをしていると、時折__call__という関数を見ることがあります。
__init__とは違い、見る機会はそれほど多くありませんが、覚えておくと便利なので紹介します。
__call__とは
__call__はPythonの特別な関数で、クラスのインスタンスを関数のように呼び出すことを可能にします。
インスタンスが関数として呼び出されるとき、__call__メソッドが定義されていると以下のように認識されます。
x(arg1, arg2, ...)
# ↑は↓の省略記法として認識される
x.__call__(arg1, arg2, ...)__call__の使い方
例として次のコードを書いてみましょう。
class Example:
def __init__(self):
print('Example object created')
def __call__(self):
print('Instance of Example class called as function')
e = Example()
e()上記のコードが実行されると、次のように出力されます。
Example object created
Instance of Example class called as function__init__はExampleクラスのインスタンスが生成されるときに呼び出されます。
それと比較して__call__は、インスタンスが関数として呼び出されるときに出力されていることがわかります。
__call__を使うメリット
Pythonのクラスで__call__を使うメリットをいくつか紹介します。
- 呼び出し可能なインスタンスの作成
クラスの中で__call__を定義することで、そのクラスのインスタンスを関数のように呼び出せます。これにより、オブジェクトの使い方がより柔軟になり、コードがより読みやすく簡潔になります。 - ステートフルな
callable
呼び出しの間に状態を保持するcallableオブジェクトを作成できます。複数の呼び出しにわたってクラスオブジェクトに関するデータを追跡する必要がある場合に便利です。 - 計算値のキャッシュ
計算値をキャッシュし、その後の呼び出しで再算出する必要がなくなります。演算が交付かな状況でパフォーマンスを向上できます。 - 明快で便利なAPIの作成
より直感的で使いやすいAPIを作成できます。他の開発者がコードにアクセスしやすくなり、新規ユーザーの学習曲線が短くなります。 - デザインパターンの実装
デコレーターパターンやストラテジーパターンなど、さまざまなデザインパターンを実装するために使用できます。コードをよりモジュール化し、保守性を高められます。
クラスオブジェクトの再利用時に使用を検討する
まとめると、__call__はクラスオブジェクトを再利用する際に使用を検討するべき特殊関数です。
小さなアプリケーションや使い捨てのコードでは使う機会はありませんが、より大きく複雑なシステムを開発するときに有用です。
使うべき機会はさほど多くありませんが、こういう書き方もできるということを覚えておくとよりスキルアップにつながります。





