gpt4 book ai didi

python - 从 Python C API 中的子类型向 tp_new 和 tp_init 传递参数

转载 作者:太空狗 更新时间:2023-10-29 20:24:32 34 4
gpt4 key购买 nike

我最初在 Python capi-sig 列表上问过这个问题:How to pass arguments to tp_new and tp_init from subtypes?

我正在阅读 Python PEP-253关于子类型化,还有很多关于如何构造类型、调用 tp_newtp_init 槽等的好建议。

但是,它缺少关于将参数从子类型传递到父类(super class)型的重要说明。似乎PEP-253根据注释未完成:

(XXX There should be a paragraph or two about argument passing here.)

所以,我正在尝试推断一些策略 well known from the Python classes 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 中的等价物是什么?

如何处理类似的情况,但派生类的特定参数预期顺序不同?它是在 args 元组末尾给出的参数(或 kwds 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)

这与上面的 ShapeColoredShape 类似。我想它也更容易处理。

谁能帮助找出上面提到的缺失的 XXX 注释以及在构造时将参数从子类型传递到父类(super class)型的正确技术?

2012-07-17 更新:

灵感来自 ecatmur's answer下面我查看了 Python 3 源代码,我找到了 collections.defaultdictdefdict_init 构造函数有趣的类型对象。该类型派生自 PyDictObject,其构造函数采用 default_factory 的附加参数。 Python 类中的构造函数签名是这样的:

class collections.defaultdict([default_factory[, ...]])

现在,这里是 default_factory 是如何从原始 args 元组中剥离的,所以其余的参数被转发到 base 的 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 函数的相关部分。

最佳答案

问题是 PyArgs_ParseTupleAndKeywords 没有提供从输入参数和关键字中提取额外的 *args**kwargs 的方法;实际上,任何额外的参数都会导致 TypeError; “函数采用 %s %d 个位置参数(给定的 %d 个)”,或“'%U' 是此函数的无效关键字参数”。

这意味着您将不得不自己解析参数和关键字;你保证 args 是一个元组,关键字是一个字典,所以你可以使用标准方法(PyTuple_GET_ITEMPyDict_GetItemString)来提取你感兴趣的参数,并识别并构造一个元组和字典以从其余部分传递。您显然不能修改 args,因为元组是不可变的;虽然从关键字中弹出项目应该没问题,但它似乎有点冒险(example crash)。

一个更雄心勃勃但绝对可行的路线是从 getargs.c ( http://hg.python.org/cpython/file/tip/Python/getargs.c ) 复制 vgetargskeywords 并扩展它以获取剩余的可选输出参数 *args**kwargs。这应该相当简单,因为您只需要修改它检测到的部分并在额外参数( extra argsextra keywords )上抛出 TypeError 。如果您选择这条路线,祝您好运。

关于python - 从 Python C API 中的子类型向 tp_new 和 tp_init 传递参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11385590/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com