【问题标题】:Python C-API: Using `PySequence_Length` with dictionariesPython C-API:将`PySequence_Length`与字典一起使用
【发布时间】:2012-03-26 17:32:11
【问题描述】:

我正在尝试使用 PySequence_Length 来获取 C 语言中 Python 字典的长度。我意识到我可以使用 PyDict_Size,但我有兴趣在某些情况下使用更通用的函数。

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

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

这失败,并打印错误:

TypeError: 'dict' 类型的对象没有 len()

我的问题是:为什么会失败?虽然 Python 字典对象不支持 Sequence 协议,但 PySequence_Lengthdocumentation 表示:

Py_ssize_t PySequence_Length(PyObject *o)

成功时返回序列 o 中的对象数,成​​功时返回 -1 失败。对于不提供序列协议的对象,这是 相当于 Python 表达式 len(o)。

由于字典类型确实具有__len__ 属性,并且由于表达式len(d)(其中d 是字典)正确返回Python 中的长度,我不明白为什么PySequence_Length 会失败C.

有什么解释吗?这里的文档不正确吗?

【问题讨论】:

    标签: python python-3.x cpython python-c-api


    【解决方案1】:

    文档具有误导性,是的。 dict 不是序列,即使它确实实现了序列协议的某些部分(对于包含测试,它们是序列协议的一部分。)Python/C 类型 API 中的这种特殊区别是不幸的,但它是几十年前做出的设计选择。文档反映了这种区别,尽管以同样尴尬的方式。它试图说明的是 对于 Python 类,它与 len(o) 相同,无论 Python 类伪装成什么。对于 C 类型,如果该类型没有实现 sizefunc 的序列版本,PySequence_Length() 将引发异常,甚至不考虑该类型是否具有 sizefunc 的映射版本。

    如果你不能完全确定你是否有序列,你应该改用PyObject_Size()。事实上,几乎没有理由打电话给PySequence_Length();通常你要么知道类型(因为你刚刚创建了它,你可以调用一个特定于类型的长度函数或宏,比如PyList_GET_SIZE()),或者你甚至不知道它是否是一个序列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-07
      • 1970-01-01
      • 2018-03-30
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 2011-03-09
      • 2019-11-14
      相关资源
      最近更新 更多