私はもともと Python の capi-sig リストでこの質問をしました:サブタイプから tp_new と tp_init に引数を渡すには?
サブタイピングに関する Python PEP-253を読んでいますが、型、呼び出しtp_new
、tp_init
スロットなどを構造化する方法について、適切な推奨事項がたくさんあります。
ただし、サブタイプからスーパータイプへの引数の受け渡しに関する重要な注意事項が欠けています。注記によると、PEP-253は未完成のようです。
(XXX ここで引数の受け渡しについて 1 つか 2 つのパラグラフが必要です。)
そのため、Python クラスのサブタイプからよく知られているいくつかの戦略、特に各レベルで引数を取り除く手法などを推定しようとしています。
これと同様の効果を達成するための手法を探していますが、プレーンなPython C API (3.x)を使用しています。
class Shape:
def __init__(self, shapename, **kwds):
self.shapename = shapename
super().__init__(**kwds)
class ColoredShape(Shape):
def __init__(self, color, **kwds):
self.color = color
super().__init__(**kwds)
Python C API で同等のものは何ですか?
同様の状況に対処する方法はありますが、異なる順序で期待される派生クラスに固有の引数がありますか? これは args タプルの最後に与えられた引数です (またはkwds
辞書、原則は同じだと思います)。
状況を示す (疑似) コードを次に示します。
class Base:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class Derived(Base):
def __init__(self, x, y, a):
self.a = a
super().__init__(x, y, None):
a
が最初に期待されていた場合は、次の点に注意してください。
Derived.__init__(self, a, x, y)
上記と同様の状況にShape
なりColoredShape
ます。また、対処も簡単になると思います。
上記の欠落しているXXXコメントと、構築時にサブタイプからスーパータイプに引数を渡すための正しいテクニックを理解するのを手伝ってくれる人はいますか?
更新 2012 年 7 月 17 日:
以下のecatmurの回答に触発されて、Python 3のソースを調べたところ、 collections.defaultdictタイプのオブジェクトdefdict_init
のコンストラクターが 興味深いことがわかりました。型は から派生し、そのコンストラクターは の追加引数を取ります。Python クラスのコンストラクタ シグネチャは次のとおりです。PyDictObject
default_factory
class collections.defaultdict([default_factory[, ...]])
ここで、default_factory
が元のタプルからどのように削除されるかを次に示しますargs
。したがって、残りの引数はtp_init
基本型の に転送されPyDictObject
ます。
int result;
PyObject *newargs;
Py_ssize_t n = PyTuple_GET_SIZE(args);
...
newargs = PySequence_GetSlice(args, 1, n);
...
result = PyDict_Type.tp_init(self, newargs, kwds);
これは、関数の関連部分のみの存在を切り取っていることに注意してくださいdefdict_init
。