1. ホーム
  2. python

[解決済み] モジュール上の __getattr__

2022-05-28 02:59:39

質問

に相当するものをどのように実装すればよいのでしょうか? __getattr__ をクラスやモジュールに実装できますか?

モジュールの静的定義属性に存在しない関数を呼び出す場合、そのモジュールにクラスのインスタンスを作成し、モジュールの属性検索で失敗したのと同じ名前のメソッドをそのモジュール上で呼び出したいと思います。

class A(object):
    def salutation(self, accusative):
        print "hello", accusative

# note this function is intentionally on the module, and not the class above
def __getattr__(mod, name):
    return getattr(A(), name)

if __name__ == "__main__":
    # i hope here to have my __getattr__ function above invoked, since
    # salutation does not exist in the current namespace
    salutation("world")

どちらが与えるか。

matt@stanley:~/Desktop$ python getattrmod.py 
Traceback (most recent call last):
  File "getattrmod.py", line 9, in <module>
    salutation("world")
NameError: name 'salutation' is not defined

どのように解決するのですか?

しばらく前に、Guido は、すべての特別なメソッドの検索が をバイパスする新しいスタイルのクラス __getattr____getattribute__ . Dunder のメソッドは、以前はモジュール上で動作していました。 __enter____exit__ の前に、そのトリックを 壊れた .

最近、いくつかの歴史的な機能がカムバックしました。 __getattr__ その中で、既存のハック (モジュールが自分自身をクラスで置き換えることで sys.modules のクラスで自分自身を置き換える) は、もはや必要ないはずです。

Python 3.7+では、1つの明白な方法を使うだけです。 モジュールの属性アクセスをカスタマイズするには、モジュールに __getattr__ 関数を定義します。この関数は一つの引数 (属性の名前) を受け取り、計算された値を返すか、または AttributeError :

# my_module.py

def __getattr__(name: str) -> Any:
    ...

これはまた、"from" インポートへのフック、すなわち、次のようなステートメントに対して動的に生成されたオブジェクトを返すことができるようになります。 from my_module import whatever .

これに関連して、モジュール getattr と一緒に __dir__ 関数をモジュールレベルで定義して dir(my_module) . 参照 PEP 562 を参照してください。