2012-03-26 71 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()),或者你甚至不知道它是否是一个序列。