mlo*_*kot 9 python python-c-api
我最初在Python capi-sig列表中提出了这个问题:如何从子类型向tp_new和tp_init传递参数?
我正在阅读关于子类型的Python PEP-253,并且有很多关于如何构造类型,调用tp_new和tp_init插槽等的好建议.
但是,它没有关于将参数从sub传递到super类型的重要说明.根据说明,PEP-253似乎未完成:
(XXX应该有一两段关于在这里传递的论点.)
所以,我试图推断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)
Run Code Online (Sandbox Code Playgroud)
Python C API中的等价物是什么?
如何处理类似的情况,但具有特定于派生类的参数以不同的顺序预期?它是在args元组结尾处给出的参数(或者kwdsdict,我假设原理是相同的).
这是一些(伪)代码,说明了这种情况:
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):
Run Code Online (Sandbox Code Playgroud)
请注意,如果a预期是第一个:
Derived.__init__(self, a, x, y)
Run Code Online (Sandbox Code Playgroud)
这将是类似的情况在Shape和ColoredShape上面.我想,处理起来也会更容易.
任何人都可以帮助找出上面提到的缺失的XXX评论和正确的技术,以便在构造中将参数从子类型传递到超类型吗?
更新2012-07-17:
受到ecatmur在下面的回答的启发,我查看了Python 3的源代码,我发现collections.defaultdict类型对象的defdict_init构造 函数很有趣.该类型派生自,其构造函数需要额外的参数.Python类中的构造函数签名是这样的:PyDictObjectdefault_factory
class collections.defaultdict([default_factory[, ...]])
Run Code Online (Sandbox Code Playgroud)
现在,这里是如何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);
Run Code Online (Sandbox Code Playgroud)
注意,这个剪切仅存在defdict_init功能的相关部分.
问题是,PyArgs_ParseTupleAndKeywords没有提供一个方法来提取额外的*args和**kwargs从输入指定参数和关键字; 实际上,任何额外的论证都会产生一个TypeError; "函数需要%s%d位置参数(%d给定)"或"'%U'是此函数的无效关键字参数".
这意味着您将不得不自己解析args和关键字; 你保证args是一个元组,关键字是一个dict,所以你可以使用标准方法(PyTuple_GET_ITEM和PyDict_GetItemString)来提取你感兴趣的参数,并识别和构造一个元组和dict从其余部分传递.你显然无法修改args,因为元组是不可变的; 虽然从关键字弹出项目应该没问题,但它看起来确实有点危险(例如崩溃).
一个更雄心勃勃但绝对可行的路线是vgetargskeywords从getargs.c(http://hg.python.org/cpython/file/tip/Python/getargs.c)复制并扩展它以获取余数*args和可选的out参数**kwargs.这应该是相当简单的,因为您只需要修改它检测到的部分并抛出TypeError额外的参数(额外的args ; 额外的关键字).祝你好运,如果你选择这条路线.
| 归档时间: |
|
| 查看次数: |
1175 次 |
| 最近记录: |