ここで発生している 2 つの基本的な問題があります。
__xxx__
メソッドはクラスでのみ検索されます
TypeError: can't set attributes of built-in/extension type 'module'
(1) どのソリューションも、どのモジュールが検査されているかを追跡する必要があることを意味します。そうしないと、すべてのモジュールがインスタンス置換動作を行うことになります。(2) は、(1) が不可能であることを意味します...少なくとも直接的には不可能です。
幸いなことに、sys.modules はそこに何が入るかについてうるさいわけではないので、ラッパーは機能しますが、モジュール アクセスに対してのみ機能します (つまりimport somemodule; somemodule.salutation('world')
、同じモジュール アクセスの場合、ほとんどの場合、置換クラスからメソッドをヤンクし、それらを別のクラスに追加する必要globals()
があります)。クラスのカスタムメソッド(私は を使用するのが好きです.export()
)またはジェネリック関数(すでに回答としてリストされているものなど)を使用します覚えておくべきこと:ラッパーが毎回新しいインスタンスを作成していて、グローバルソリューションがそうでない場合ああ、同時に両方を使用することはできません-どちらか一方です.
アップデート
グイド・ヴァン・ロッサム より:
実際には、時々使用され、推奨されるハックがあります。モジュールは、必要な機能を持つクラスを定義し、最後に、sys.modules 内の自分自身をそのクラスのインスタンス (または、主張する場合はクラス) に置き換えることができます。 、しかしそれは一般的にあまり役に立ちません)。例えば:
# module foo.py
import sys
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
sys.modules[__name__] = Foo()
これが機能するのは、インポート機構が積極的にこのハックを有効にしているためです。また、最後のステップとして、実際のモジュールをロード後に sys.modules から引き出します。(これは偶然ではありません。ハックはずっと前に提案されていたので、輸入機械でそれをサポートするのに十分だと判断しました。)
したがって、目的を達成するための確立された方法は、モジュール内に単一のクラスを作成し、モジュールの最後の動作としてクラスのインスタンスに置き換えることです。これで、必要に応じて/ /sys.modules[__name__]
で遊ぶことができます。__getattr__
__setattr__
__getattribute__
注 1 : この機能を使用すると、モジュール内の他のもの (グローバル、その他の関数など) がsys.modules
割り当て時に失われます。そのため、必要なものがすべて置換クラス内にあることを確認してください。
注 2 : サポートするには、クラスで定義from module import *
する必要があります。__all__
例えば:
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
__all__ = list(set(vars().keys()) - {'__module__', '__qualname__'})
Python のバージョンによっては、省略できる名前が他にもある場合があります__all__
。Python 2 とのset()
互換性が不要な場合は、 を省略できます。