我最初在 Python capi-sig 列表中问了这个问题:How to pass arguments to tp_new and tp_init from subtypes?
我正在阅读关于子类型化的 Python PEP-253,关于如何构造类型、调用tp_new
和tp_init
插槽等有很多很好的建议。
但是,它缺少关于将参数从 sub 类型传递到 super 类型的重要说明。根据注释, PEP-253似乎未完成:
(XXX 这里应该有一两段关于参数传递的内容。)
因此,我试图从 Python 类 subtyping 中推断出一些众所周知的策略,尤其是每个级别剥离参数的技术等。
我正在寻找实现与此类似效果的技术,但使用普通的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 中的等价物是什么?
如何处理类似的情况,但特定于派生类的参数以不同的顺序预期?kwds
它是在 args 元组(或dict,我认为原理相同)末尾给出的参数。
下面是一些(伪)代码来说明这种情况:
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
函数的相关部分。