2012-03-26 35 views
2

我試圖用PySequence_Length來獲取C語言中的Python字典的長度。我意識到我可以使用PyDict_Size,但我有興趣使用更通用的函數在某些情況下。Python C-API:在字典中使用'PySequence_Length'

PyObject* d = PyDict_New(); 
Py_ssize_t res = PySequence_Length(d); 

printf("Result : %ld\n", res); 
if (res == -1) PyErr_Print(); 

這種失敗,並打印錯誤:

TypeError: object of type 'dict' has no len()

我的問題是:爲什麼會失敗?雖然Python字典對象不支持的協議序列,所述documentationPySequence_Length說:

Py_ssize_t PySequence_Length(PyObject *o)

Returns the number of objects in sequence o on success, and -1 on failure. For objects that do not provide sequence protocol, this is equivalent to the Python expression len(o).

由於字典類型並具有__len__屬性,並且由於表達len(d)(其中d是一個字典)適當地返回Python的長度,我不明白爲什麼PySequence_Length應該在C失敗。

任何解釋?文檔不正確嗎?

回答

4

該文檔具有誤導性,是的。字典不是一個序列,即使它實現了序列協議的某些部分(對於包含測試,它們是序列協議的一部分)。Python/C類型API中的這種特殊區別是不幸的,但它是一種人爲因素幾十年前的設計選擇。文件反映了這種區別,雖然同樣尷尬。它試圖說的是,對於Python類而言,len(o)是一樣的,無論Python類假裝是什麼。對於C類型,如果類型沒有實現sizefunc的序列版本,則PySequence_Length()將引發異常,而不考慮該類型是否具有sizefunc的映射版本。

如果您不完全確定您是否有序列,則應該使用PyObject_Size()代替。事實上,沒有什麼理由叫PySequence_Length();通常你要麼知道類型(因爲你剛剛創建了它,而且你可以調用類型特定的長度函數或宏,如PyList_GET_SIZE()),或者你甚至不知道它是否是一個序列。