__weakref__
と__dict__
の定義は、その適切な記述は、Pythonレベルのコードは、それを探したときに弱参照リストの「本物」の場所とクラスのインスタンスのインスタンス辞書にアクセスするために呼び出されています。基底クラスobject
は無骨であり、__weakref__
または__dict__
(weakref.ref(object())
が失敗するようにsetattr(object(), 'foo', 0)
)のスペースを予約しません。
ユーザ定義クラスの場合、これらの値を見つけるための記述子を定義する必要があります(CPythonでは、Cレイヤに直接ポインタがあるため、これらのアクセサは通常バイパスされますが、instance.__dict__
を明示的に参照する場合、インスタンスのクラスを通してそれを見つける方法を知っている)。 object
の最初の子(__slots__
なし)は、これらの記述子を定義する必要があります。サブクラスは、__dict__
と__weakref__
の位置が変更されないため、必要ありません。それらのインスタンスは同じ相対的なオフセットでそれらの属性を持つため、引き続き基本クラスのアクセサーを使用できます。
基本的に、第一の非__slot__
-edユーザ定義クラスがフォームのC構造体としてインスタンスの考えを作成している:
struct InstanceObject {
... common object stuff ...
... anything defined by __slots__ in super class(es), if anything ...
PyObject *location_of___dict__;
PyObject *location_of___weakref__;
}
とアクセサを決定するために、型を確認するために実装されています構造体メンバのlocation*
のオフセットを取得してからそれらを取得します。子クラスのstruct
定義では、location*
メンバーのオフセットは変更されません(新規の場合は__slots__
が追加され、追加されたばかりです)ので、親から同じアクセサを再利用できます。
注:これはすべてCPythonの実装の詳細であり、いつでも変更される可能性があります。彼らが望むのであれば、 '__dict__'と' __weakref__'のアクセサをサブクラスにコピーして、 '__dict__' /' __weakref__'が直接アクセスされたときに追加のルックアップを節約することができますが、(注記したように)CPythonはアクセサコードはそれらを直接アクセスします(CレベルのものはPython可視アクセッサをバイパスします)。そのような最適化(おそらく各クラス定義のためのより多くのメモリを犠牲にして)はおそらく価値がないと考えられます。 – ShadowRanger