バインドされたメソッド、継承、およびgetattrの間の相互作用で、私が理解できていない奇妙なことが起こっています。
私は次のようなディレクトリ設定をしています:
/a
__init__.py
start_module.py
/b
__init__.py
imported_module.py
import_module.pyには、次の形式のクラスオブジェクトがいくつか含まれています。
class Foo(some_parent_class):
def bar(self):
return [1,2,3]
start_module.pyの関数は、inspectを使用して、imported_module.pyのクラスを表す文字列のリストを取得します。「Foo」はそれらの文字列の最初のものです。目標は、その文字列とgetattrを使用してstart_module.pyでbarを実行することです。*
これを行うには、次の形式のstart_moduleのコードを使用します。
for class_name in class_name_list:
instance = getattr(b.imported_module, class_name)()
function = getattr(instance, "bar")
for doodad in [x for x in function()]:
print doodad
これはリスト内包表記の反復を正常に開始しますが、最初の文字列「bar」で奇妙なエラーが発生します。バーはバインドされたメソッドですが、Fooのインスタンスを引数として期待していることを理解している限り、次のように言われます。
TypeError:bar()は引数を取りません(1つ指定)
これにより、function()の呼び出しがFooインスタンスを渡しているように見えますが、コードはそれを受け取ることを期待していません。
私はここで何が起こっているのか本当にわかりませんし、GoogleとStackOverflowを見て説明を解析することもできませんでした。ダブルgetattrは奇妙な相互作用を引き起こしていますか?Pythonのクラスオブジェクトについての私の理解はあまりにも曖昧ですか?私はあなたの考えを聞いてみたいです。
*アンチパターンを回避するための実際の最終目的は、start_module.pyがimported_module.pyのFooと同様のさまざまなクラスの名前バーのすべてのメソッドに自動的にアクセスできるようにすることです。私は、後継者がFooに似たクラスの数が非常に多い可能性があるもののリストを維持することを回避することを期待してこれを行っています。
以下の回答:ここでの最大のポイントは、検査が非常に役立つことです。発生しているバグの一般的な原因がある場合は、他の可能性を探す前に、それを除外したことを絶対に確認してください。この場合、ファイル構造が最近編集されたために、正しいコードを持っているモジュールがインポートされていない可能性があるという事実を見落としていました。