2016-03-05 77 views
2

我正在開發Python 3 C擴展。Python C擴展中的True * args和** kwargs

我可以得到等價的或任意的位置或關鍵字參數嗎?

例如,在Python,我可以這樣寫:

def fun(name, parent, *args, **kwargs): 
    # do something with name and parent 
    # do something with args and kwargs 
    pass 

但我不能找到一個簡單的等同於C的同時,我們可以完美地寫函數與PyObject* argsPyObject* kwargs,我不能輕易「解析出」名字和父母從它來的任何(args/kwargs)。

採取:

static PyObject* myFunction(PyObject* self, PyObject* args, PyObject* kwargs) { 
    char* kwds[] = {"parent", "name", NULL}; 
    PyObject* name = NULL; 
    PyObject* parent = NULL; 
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwds, &parent, &name)) { 
     goto errorParseTupleAndKeywords; 
    } 
    /* Do something with name and parent */ 
    /* parent and name maybe have appeared either in args or kwargs */ 
    /* But I don't have any extra positional (*args) or keyword (**kwargs) here */  
} 

A 「手冊」 的方法,我能想到看起來大致是:

static PyObject* myFunction(PyObject* self, PyObject* args, PyObject* kwargs) { 
    PyObject* name = NULL; 
    PyObject* parent = NULL; 
    int inKwargs = 0; 
    // Pretend to do something with parent 
    if (PyDict_GetItemString(kwargs, "parent")) { 
     inKwargs++; 
     PyDict_DelItemString(kwargs, "parent"); 
    } 
    // Pretend to do something with name 
    if (PyDict_GetItemString(kwargs, "name")) { 
     inKwargs++; 
     PyDict_DelItemString(kwargs, "name"); 
    } 
    // Not sure if -1 works here 
    PyObject* newArgs = PyTuple_GetSlice(args, inKwargs, -1); // this is *args 
    // the remaining kwargs can be used as **kwargs 
} 
+0

'args'和'kwargs'都不是特別的,只是傳統的元組和字典! – cdonts

回答

2

在C API,PyObject* args真的是一個Python元組和PyObject* kwargs真的是一個Python字典。至少,這是什麼PyArg_ParseTupleAndKeywords internally要求:

int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *keywords, const char *format, char **kwlist, ...) 
{ 
    // … 
    if ((args == NULL || !PyTuple_Check(args)) || 
     (keywords != NULL && !PyDict_Check(keywords)) || 
     format == NULL || 
     kwlist == NULL) 
    { 
     PyErr_BadInternalCall(); 
     return 0; 
    } 

    // … 
} 

實際執行中vgetargskeywords該功能也再次發出這個,所以你應該罰款與由畫手工提取更換您的通話PyArg_ParseTupleAndKeywords

這意味着您可以同時使用tupledict API,也可以使用iterator protocol遍歷這些對象中的項目。

+2

是的,我知道'PyObject * args'是一個元組,而'PyObject * kwargs'是一個字典;在問題的第三個代碼塊(「手動」方法)中,我使用了元組和字典API。不足之處在於代碼需要極大的空間並且不太易讀,也就是說,你不能立即從這15行中得知它們的意圖是像'def fun(name,parent,* args, ** kwargs)'。 – jleeothon