Pythonドキュメントの「データモデル」の章の「新しいスタイルのクラスの特別なメソッドルックアップ」セクションから(太字の強調鉱山):
新しいスタイルのクラスの場合、特別なメソッドの暗黙的な呼び出しは、オブジェクトのインスタンス ディクショナリではなく、オブジェクトの型で定義されている場合にのみ正しく動作することが保証されます。その動作が、次のコードが例外を発生させる理由です (古いスタイルのクラスの同等の例とは異なります)。
>>> class C(object): ... pass ... >>> c = C() >>> c.__len__ = lambda: 5 >>> len(c) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: object of type 'C' has no len()
この動作の背後にある理論的根拠は、型オブジェクトを含むすべてのオブジェクトによって実装される
__hash__()
や などの多くの特別なメソッドにあります。__repr__()
これらのメソッドの暗黙的なルックアップで従来のルックアップ プロセスが使用された場合、型オブジェクト自体で呼び出されたときに失敗します。>>> 1 .__hash__() == hash(1) True >>> int.__hash__() == hash(int) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor ’__hash__’ of ’int’ object needs an argument
この方法でクラスのバインドされていないメソッドを誤って呼び出そうとすることは、「メタクラスの混乱」と呼ばれることがあり、特別なメソッドを検索するときにインスタンスをバイパスすることで回避されます。
>>> type(1).__hash__(1) == hash(1) True >>> type(int).__hash__(int) == hash(int) True
太字の単語がうまく聞き取れません…</p>