在Python中,什么是PyObject?

36

简短版本

我最近在 Python 代码中看到一个函数的返回类型被指定为 PyObject,在文档中有说明。那么,PyObject 是什么?

详细版本

虽然我不是 C/C++ 程序员,但当我在上面链接的文档中看到 PyObject 时,我通过 Google 发现 PyObject 是使用 Python/C API 定义的 Python 对象。具体来说,API 文档如下定义 PyObject:

所有对象类型都是这种类型的扩展。这是一种类型,其中包含 Python 需要处理指向对象的指针作为对象所需的信息。在正常的“发布”版本中,它仅包含对象的引用计数和指向相应类型对象的指针。它对应于 PyObject_HEAD 宏的扩展定义中定义的字段。

坦白地说,我并不完全理解这个定义,也不知道它是否回答了我的基本问题,但这并不使我认为将 PyObject 简单地视为 Python 对象是显然错误的。另一方面,也许为了严格算作 PyObject,该类型必须使用 Python/C API 作为标准 Python 的扩展创建。例如,整数是 PyObject 吗?

可能相关的链接

  • https://numpy.org/doc/stable/user/c-info.beyond-basics.html#adding-the-new-data-type
  • 这是一个关于NumPy添加新数据类型的教程页面。

    1
    您可以在此处 https://github.com/python-git/python/blob/master/Include/stringobject.h 中查看 PyObject C 类型的用法示例,例如 Python 字符串的 C 定义。 - Jivan
    还要注意的是,据我所知,Python是纯C而不是C ++。 - Jivan
    @Jivan 我认为扩展可以同时使用C++,但如果这是错误的话,我可以删除C++标签... - eric
    我并不是要求您移除标签,我只是想为了准确性而进行一些调整 :) - Jivan
    2个回答

    30

    在Python中,您可以接触到的每个值都是在C中的PyObject。这包括列表、字典、套接字、文件、整数、字符串、函数、类等等。如果在Python中能够接触到它,那么它就是在C中的PyObject


    我看到两种解释:一方面,如果有人在他们的文档中将PyObject指定为输入参数类型,则基本上意味着“任何您想要的都可以作为输入”。另一方面,如果在C语言中它技术上是一个PyObject *,那么在Python中将其命名为输入参数是否是一个错误?请注意,文档在此处:http://srinikom.github.io/pyside-docs/PySide/QtCore/QAbstractItemModel.html#PySide.QtCore.PySide.QtCore.QAbstractItemModel.createIndex - eric
    我刚刚注意到 PyQt 这个 Python Qt 的替代绑定实际上使用了相同的参数名 object,而不是 PyObject:http://pyqt.sourceforge.net/Docs/PyQt4/qabstractitemmodel.html#createIndex 另外,在实践中,当我们使用该函数时,我们将其提供给它通常的 Python 对象,绝对不会期望该输入是通过使用 API 显式创建的 Python 扩展。 - eric
    3
    @neuronet: 在Python文档中说某个东西是PyObject可能是一个错误,但是这样的错误有些情有可原。我认为PySide部分是自动生成的,代码生成器可能没有特别指定“PyObject不应该出现在Python文档中”。而且,PyObject是可以在Python中操作的任何对象,即使它是由Python定义的,也不一定非要由扩展定义。通过说它接受一个PyObject,就是说它接受任何值。 - icktoofay

    16

    PyObject实际上只是C级别下的Python对象。由于Python中的整数也是对象,因此它们也是PyObject。无论是用Python还是C编写的,它在C级别下都是一个PyObject


    那么我有一个问题,就是我问icktoofay的:如果PyObject只在C级别定义,那么在Python级别将其指定为输入类型是否技术上是错误的?例如,Python函数的输入应该只被输入为“任何”或其他全包容性术语吗? - eric
    1
    @neuronet:Python函数的参数是无类型的。Python函数的C后端实现的参数不能是无类型的。 - Ignacio Vazquez-Abrams
    我认为我理解了:它们是未经类型声明的,因此在参数列表中没有显式声明类型。尽管如此,有时它们确实期望某些类型(即,在Python中存在“TypeErrors”)。请参见评论中指向icktoofay的链接,以查看我所指的文档及其对预期输入参数类型的描述。此外,如果您输入a=str,那在Python中就可以了。但是尝试输入a = PyObject。你会得到NameError。我能说以下内容吗:PyObject是一种c类型,由c用于定义Python类。但它不是Python内部的标准类型 - eric
    2
    @neuronet:那份文档破坏了Python与其实现之间的抽象。实际上并没有负面影响,但如果你不了解实现细节,阅读起来可能会令人困惑。 - Ignacio Vazquez-Abrams

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接