[解決済み] PythonicなDependency Injectionの方法とは?
質問
はじめに
Java では、依存性注入は純粋な OOP として動作します。すなわち、実装するインターフェースを提供し、フレームワークのコードで、定義されたインターフェースを実装しているクラスのインスタンスを受け取ります。
Pythonでも同じようなことができますが、Pythonの場合、この方法はオーバーヘッドが大きすぎると思います。では、Pythonの場合はどのように実装するのでしょうか?
使用例
これがフレームワークのコードだとします。
class FrameworkClass():
def __init__(self, ...):
...
def do_the_job(self, ...):
# some stuff
# depending on some external function
基本的な考え方
最も単純な (そしておそらく最良の?) 方法は、外部関数を
FrameworkClass
のコンストラクタから呼び出されるようにすることです。
do_the_job
メソッドから呼び出されます。
フレームワークのコードです。
class FrameworkClass():
def __init__(self, func):
self.func = func
def do_the_job(self, ...):
# some stuff
self.func(...)
クライアントコードです。
def my_func():
# my implementation
framework_instance = FrameworkClass(my_func)
framework_instance.do_the_job(...)
質問
質問は短いです。これを行うために、より良い一般的に使用されるPythonic方法はありますか?または多分そのような機能をサポートしている任意のライブラリ?
UPDATE: 具体的な状況
私が、トークンを使って認証を行うマイクロウェブフレームワークを開発したとします。このフレームワークでは、いくつかの
ID
に対応するユーザを取得する関数が必要です。
ID
.
明らかに、フレームワークはユーザーもしくはほかのアプリケーション固有のロジックについて何も知らないので、クライアントコードは認証を動作させるためにユーザーゲッター機能をフレームワークに注入しなければなりません。
どのように解決するのでしょうか?
参照 Raymond Hettinger - 超考えたスーパー! - PyCon 2015 にて、DIではなくsuperと多重継承を使う方法について議論しています。動画を全部見る時間がない場合は、15分までジャンプしてください(でも全部見ることをお勧めします)。
このビデオで説明されていることをどのように適用するか、例を挙げてみましょう。
フレームワークのコードです。
class TokenInterface():
def getUserFromToken(self, token):
raise NotImplementedError
class FrameworkClass(TokenInterface):
def do_the_job(self, ...):
# some stuff
self.user = super().getUserFromToken(...)
クライアントコードです。
class SQLUserFromToken(TokenInterface):
def getUserFromToken(self, token):
# load the user from the database
return user
class ClientFrameworkClass(FrameworkClass, SQLUserFromToken):
pass
framework_instance = ClientFrameworkClass()
framework_instance.do_the_job(...)
これはPython MROが(super()が使われていれば)getUserFromTokenクライアントメソッドが呼ばれることを保証するため、動作します。Python 2.xを使用している場合は、コードを変更する必要があります。
ここでの1つの付加的な利点は、クライアントが実装を提供しない場合、これは例外を発生させるということです。
もちろん、これは本当の依存性注入ではなく、多重継承とミキシンですが、あなたの問題を解決するためのPythonicな方法です。
関連
-
[解決済み] for'ループでインデックスにアクセスする?
-
[解決済み] __init__.py は何のためにあるのですか?
-
[解決済み] パラメータに**(ダブルスター/アスタリスク)、*(スター/アスタリスク)がありますが、これはどういう意味ですか?
-
[解決済み] 複数行の長い文字列を作成するためのPythonicな方法
-
[解決済み] Inversion of ControlとDependency Injectionの比較
-
[解決済み】if __name__ == "__main__": は何をするのでしょうか?
-
[解決済み】forループを使った辞書の反復処理
-
[解決済み] Pythonの構文に新しいステートメントを追加することはできますか?
-
[解決済み] django.db.migrations.exceptions.InconsistentMigrationHistory
-
[解決済み] Ctrl-CでPythonスクリプトを終了できない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Pandasのデータフレームでタプルの列を分割するにはどうしたらいいですか?
-
[解決済み] Flaskで1時間ごとに関数を実行するようにスケジュールするには?
-
[解決済み] 値で列挙名を取得する [重複]。
-
[解決済み] 範囲指定された浮動小数点数のランダムな配列を生成します。
-
[解決済み] pandasのタイムゾーンに対応したDateTimeIndexを、特定のタイムゾーンに対応したナイーブなタイムスタンプに変換する。
-
[解決済み] サブフォルダからのインポートモジュール
-
[解決済み] Python Logging でログメッセージが2回表示される件
-
[解決済み] Pythonの文字列書式をリストで使う
-
[解決済み] Pythonの文字列の前にあるbという接頭辞は何を意味するのですか?
-
[解決済み] 認証プラグイン 'caching_sha2_password' はサポートされていません。