在 python C api 中将可迭代对象转换为元组

Convert an iterable object to tuple in python C api

我有一个可迭代的 PyObject,我需要将其作为参数列表传递给 Python 可调用对象,ala

xs = [1,2,5,7]
some_function(*xs)

但是,PyObject_CallObject 只允许将元组作为参数的容器传递。

不过,我不确定创建包含可迭代元素的新元组的最佳方法是什么。这是一个暂定代码:

PyObject* unpack_call(PyObject* callable, PyObject* args) {
  PyObject* tuple;
  if (PyTuple_Check(args)) {
    tuple = args;
  } else {
    PyObject* iter = PyObject_GetIter(args);
    if (!iter) return NULL;

    tuple = PyTuple_New(0);

    for (Py_ssize_t pos=0; ; ++pos) {
      PyObject* arg = PyIter_Next(iter);
      if (!arg) break;

      PyTuple_SetItem(tuple,pos,arg);
    }
  }
  return PyObject_CallObject(callable,tuple);
}

我不确定是否需要自己增加元组的大小。令我困惑的是 documentation 中的句子:

The tuple will always grow or shrink at the end.

我也不确定是否需要增加或减少任何这些对象的引用计数。

你最好使用 PySequence_Tuple,它可以直接从可迭代对象创建元组。可能还有其他类似的选项可以做到这一点。

如果您确实想按照自己的方式进行操作,那么每次添加时都需要调用 PyTuple_Resize(或可能调整其大小)。什么句子

The tuple will always grow or shrink at the end.

告诉你额外的 space 在元组的末尾。

PyTuple_SetItem 窃取一个引用,因此您无需更改要添加的项目的引用计数。你应该做一些错误检查 - PyIter_Next 可以引发异常。完成后,您还需要递减 iter 和元组。