我正在编写functools.partialobject alternative,它累加参数,直到它们的数目足以进行调用。
我使用C API,并且我有tp_call实现,当它被调用时,返回self或PyObject*的修改版本。
起初,我遵循Defining New Types指南,然后意识到,我无法从PyObject *实现返回不同的类型(MyObject*tp_call)。
然后我尝试不使用structMyObject*定义,而是在PyObject_SetAttrString中使用tp_init,就像我们在Python中那样。但在这种情况下,我得到了AttributeError,因为您不能在Python中的object实例上设置任意属性。
这里我需要的是使我的tp_call实现具有多态性,并使它能够返回MyObject的子类PyObjectPyObject类型本身。
做那件事的明智方法是什么?
更新#0
这就是密码:

static PyObject *Curry_call(Curry *self, PyObject *args,
                            PyObject *kwargs) {
    PyObject * old_args = self->args;
    self->args = PySequence_Concat(self->args, args);
    Py_DECREF(old_args);
    if (self->kwargs == NULL && kwargs != NULL) {
        self->kwargs = kwargs;
        Py_INCREF(self->kwargs);
    } else if (self->kwargs != NULL && kwargs != NULL) {
        PyDict_Merge(self->kwargs, kwargs, 1);
    }

    if ((PyObject_Size(self->args) +
         (self->kwargs != NULL ? PyObject_Size(self->kwargs) : 0)) >=
        self->num_args) {
        return PyObject_Call(self->fn, self->args, self->kwargs);
    } else {
        return (PyObject *)self;
    }
}

更新#1
为什么我最初放弃了这个实现-因为我在随后的部分对象调用中得到了segfault。我认为这是因为从Curry *PyObject*的问题。但现在我已经通过在返回之前添加Py_INCREF(self);来修复segfault。对我来说很奇怪。如果我按C API所有权规则返回self,我真的应该增加self吗?

最佳答案

如果您已经正确定义了MyObject类型,那么您应该能够简单地将MyObject *转换为PyObject *并返回它。MyObject的第一个成员是一个PyObject,C允许您将指向结构的指针转换为指向结构的第一个成员的指针,反之亦然。我相信这个特性是专门允许这样的。

关于python - 如何在Python C API中实现多态?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29575854/

10-11 21:21