为`tp_repr`和`tp_str`搜索“简单”方法

时间:2015-01-28 14:20:43

标签: python python-c-api

我在C中创建了一个Python扩展,因为它具有友好的结构和高效的用法。因此,对于某些繁重的操作有很多源代码应该在C中。并且引用了许多内部字段。

现在,我将进行一些美学改进:主要是tp_reprtp_str位置。我必须用C做吗?我认为在Python中使用它们应该很容易,但用C编写它似乎是一场噩梦并且毫无用处。

我有内部字段,如编码二进制字符串,字典等。使用Python功能似乎很简单:

def repr_func(obj):
    return "MyObject(name='%s'.encode('utf-16-be'), id=%d, map=%s)"
            % (obj.name.decode("utf-16-be"), obj.id, repr(obj.map))

我知道我可以在C中做到这一点,但在Python中做这件事似乎更清晰。我不需要性能,那些将用于调试和测试,所以我需要它们有用和干净。

如果没有C源的深层变化,有没有办法做到这一点?

1 个答案:

答案 0 :(得分:2)

在编程中经常这样,有不同的方法可以完成任务。

您在Python中所做的事情,可以通过类似

之类的东西在C(Pyhton 2. *)中实现
static PyObject * repr (Obj *self) {
    PyObject *map = PyObject_Repr(self->map);
    if (!map) return NULL;
    char *map_repr = PyString_AsString(map);
    PyObject *repr = PyString_FromFormat(
        "MyObject(name='%s'.encode('utf-16-be'), id=%d, map=%s)",
            self->name, self->id, map_repr);
    Py_DECREF(map);
    return repr;
}

并假设您的对象的typedef为Obj且名称为char *。如果是PyObeject *,您可以使用PyString_AsDecodedObject进行解码。在Python 3. *中,您可能需要使用PyUnicode_*PyBytes_*函数。

如果你想使用纯Python中定义的函数,你可以通过导入模块来实现,它定义了这些函数,如

static PyObject * repr (Obj *self) {
    PyObject *module = PyImport_ImportModule("repr_mod");
    if (!module) return NULL;
    PyObject *repr = PyObject_CallMethod(module, "repr_func", "(O)", self);
    Py_DECREF(module);
    return repr;
}

其中repr_mod是模块的名称。

最后,您只需在初始化类型时将tp_repr设置为(reprfunc) repr

我不会考虑C源的深层变化,所以也许只是你正在寻找的东西。