我尝试使用pythoncapi实现一个Python函数,该函数的功能类似于(此实现被简化,并且不包括键的NULL检查):
def my_func(arg1, arg2 = 2, **kwargs):
if arg2 == 1:
# expect certain parameters to be in kwargs
if arg2 == 2:
# expect different parameters to be in kwargs
if arg2 == 3:
# call a Python function with the kwargs (whats in the kwargs is unknown)
PythonFunc(**kwargs)
arg1和arg2可以是命名参数,也可以是未命名参数
我想到的最好的办法是:
PyObject* my_func(PyObject* /*self*/, PyObject* args, PyObject* keywds) {
PyObject* arg1, arg2;
switch(PyTuple_Size(args)) {
case 0:
arg1 = PyDict_GetItemString(keywds, "arg1");
if (arg2) PyDict_DelItemString(keywds, "arg1");
else // throw TypeError
arg2 = PyDict_GetItemString(keywds, "arg2");
if (arg2) PyDict_DelItemString(keywds, "arg2");
break;
case 1:
arg1 = PyTuple_GET_ITEM(args, 0);
if (PyDict_GetItemString(keywds, "arg1")) // throw TypeError
arg2 = PyDict_GetItemString(keywds, "arg2");
if (arg2) PyDict_DelItemString(keywds, "arg2");
break;
case 2:
arg1 = PyTuple_GET_ITEM(args, 0);
if (PyDict_GetItemString(keywds, "arg1")) // throw TypeError
arg2 = PyTuple_GET_ITEM(args, 1);
if (PyDict_GetItemString(keywds, "arg2")) // throw TypeError
break;
default:
// throw TypeError
}
if (...) // parse remaining keywds according to requirements
else // call Python functions using the remaining keyword arguments
}
当函数具有更多参数时,这可能变得非常广泛。是否有更简单的方法来实现此行为,例如使用PyArg_ParseTupleAndKeywords
不能直接使用
PyArg_ParseTupleAndKeywords
,因为它需要设置所有可能的关键字参数。它没有“任何剩余参数都是关键字”模式使用它的一个选项是将
arg1
和arg2
复制/移动到另一个dict并将其馈送到PyArg_ParseTupleAndKeywords
:显然这有点长,但与switch语句不同,它可以很好地自动添加更多参数
另一种选择是编写循环而不是switch语句。它没有什么太复杂的,而且很容易扩展。在这个版本中,您将避免
PyArg_ParseTupleAndKeywords
(因为您实际上已经实现了它的一部分)清理只是
Py_XDECREF
在parsed_args
上的一个简单循环,因此可以由共享的goto
处理相关问题 更多 >
编程相关推荐