super 経由で呼び出すときに、演算子ではなく __dunder__ メソッドを使用する必要があるのはなぜですか? 質問する

super 経由で呼び出すときに、演算子ではなく __dunder__ メソッドを使用する必要があるのはなぜですか? 質問する

__getitem__通常のオペレータ アクセスではなく、なぜ使用する必要があるのですか?

class MyDict(dict):
    def __getitem__(self, key):
        return super()[key]

我々が得るTypeError: 'super' object is not subscriptable

代わりに を使用する必要がありますsuper().__getitem__(key)が、その理由を完全に理解したことはありませんでした。オペレーターのアクセスを許可する方法で super を実装できないのは、一体何なのでしょうか?

Subscriptable は単なる例ですが、、、などについても同じ質問があり__getattr__ます__init__

ドキュメント理由を説明しようとしましたが、理解できませんでした。

ベストアンサー1

CPythonのバグトラッカーの問題 805304、「スーパーインスタンスはアイテムの割り当てをサポートしていません」レイモンド・ヘッティンガーが認識されている困難について詳しく説明してくれます。

これが自動的に機能しない理由は、プロキシされたメソッドは実行時に見つかるのに対し、Python はメソッドをキャッシュするため、そのようなメソッドはクラスで定義する必要があるためです。

彼は提案するパッチこの機能のサブセットが提供されます:

+   if (o->ob_type == &PySuper_Type) {
+       PyObject *result;
+       result = PyObject_CallMethod(o, "__setitem__", "(OO)", key, value);
+       if (result == NULL)
+           return -1;
+       Py_DECREF(result);
+       return 0;
+   }
+ 

それは明らかに可能

しかし、彼は次のように結論づけている。

私は、これをそのままにして、スーパー オブジェクトが明示的な属性検索時にのみその機能を実行することを文書化するだけでよいと考えていました。

それ以外の場合、これを完全に修正するには、スロット テーブルから関数を直接呼び出すすべての場所を Python で調べ、スロットが空の場合は属性検索を使用して後続の呼び出しを追加する必要があります。

repr(obj) のような関数の場合、ターゲット オブジェクトの __repr__() メソッドへの呼び出しを転送するのではなく、スーパー オブジェクトが自身を識別するようにする必要があると思います。

__dunder__メソッドがプロキシ化されている場合、どちらかが__repr__プロキシ化されているか、またはメソッド間に矛盾がある、というのが議論のようですsuper()。したがって、プログラマーの不気味の谷に相当するものに近づきすぎないように、そのようなメソッドをプロキシ化したくないかもしれません。

おすすめ記事