36

Short version

I recently came across some Python code in which the return type for a function was specified as PyObject in the documentation. What is a PyObject?

Detailed version

I am not a C/C++ programmer, but when I ran into PyObject in the documentation linked above, Google taught me that PyObject is a Python object as defined using the Python/C API. Specifically, the API documentation defines PyObject as follows:

All object types are extensions of this type. This is a type which contains the information Python needs to treat a pointer to an object as an object. In a normal “release” build, it contains only the object’s reference count and a pointer to the corresponding type object. It corresponds to the fields defined by the expansion of the PyObject_HEAD macro.

Frankly, I don't fully understand this, or whether it answers my basic question, but it doesn't make me think it is obviously wrong to just think of a PyObject as a Python object, full stop. On the other hand, perhaps to technically count as a PyObject the type must have been created as an extension to standard Python using the Python/C API. For instance, is an integer a PyObject?

Potentially relevant links

Yaakov Bressler
  • 9,056
  • 2
  • 45
  • 69
eric
  • 7,142
  • 12
  • 72
  • 138
  • 1
    You can grasp an idea of how PyObject C type is used for instance in the C definition of a Python string here https://github.com/python-git/python/blob/master/Include/stringobject.h – Jivan Dec 29 '14 at 05:37
  • Also note that as far as I know, Python is pure C, not C++ – Jivan Dec 29 '14 at 05:38
  • @Jivan I thought the extensions could work with either, but I can remove c++ tag if that is wrong... – eric Dec 30 '14 at 00:34
  • I didn't mean to ask you to remove the tag, I just wanted to make the precision just in case :) – Jivan Dec 30 '14 at 10:56

2 Answers2

30

Every value you can touch in Python is a PyObject in C. That includes lists, dictionaries, sockets, files, integers, strings, functions, classes, you name it. If you can touch it in Python, it’s a PyObject in C.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • I see two interpretations, then: if someone specifies `PyObject` as an input parameter type in their documentation, on one hand it basically means 'Anything you want can be an input'. On the other hand, if it is technically a PyObject *in C*, isn't it a mistake to name it as an input parameter *in Python*? Note the documentation is here: http://srinikom.github.io/pyside-docs/PySide/QtCore/QAbstractItemModel.html#PySide.QtCore.PySide.QtCore.QAbstractItemModel.createIndex – eric Dec 29 '14 at 06:05
  • I just noticed that PyQt, the alternative Python Qt binding, actually calls the same parameter `object`, instead of `PyObject`: http://pyqt.sourceforge.net/Docs/PyQt4/qabstractitemmodel.html#createIndex Also, in practice, when using that function we feed it run-of-the-mill Python objects, definitely without any expectation that the input was explicitly created via extension of Python using the API. – eric Dec 29 '14 at 06:16
  • 3
    @neuronet: Yes, it’s probably a mistake to say something is a `PyObject` in Python documentation, but it is somewhat understandable why it may exist there, as I believe PySide is partially automatically generated, and that code generator may not have special-cased “`PyObject` should not appear in Python documentation”. And `PyObject` is any object that can be touched in Python, *even if it was defined in Python*. It doesn’t have to be defined by an extension. By saying it takes a `PyObject`, it is saying it accepts any old value. – icktoofay Dec 29 '14 at 06:25
16

A PyObject is in fact just a Python object at the C level. And since integers in Python are objects, they are also PyObjects. It doesn't matter whether it was written in Python or in C, it is a PyObject at the C level regardless.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • then I have the question I asked icktoofay: if PyObject is only defined at the C level, does that mean it is technically a mistake to specify it as an input type to a function *at the Python level*? E.g., should the input to the Python function just be typed as *any* or some other all-inclusive term? – eric Dec 29 '14 at 06:12
  • 1
    @neuronet: Arguments to Python functions are untyped. Arguments to the C backing implementation of a Python function cannot be untyped. – Ignacio Vazquez-Abrams Dec 29 '14 at 06:17
  • I think I understand: they are untyped in that the type is not explicitly declared in the parameter list. That said, they do expect certain types sometimes (i.e., there do exist `TypeErrors` in Python). See links in comments to icktoofay to see the documentation I was referring to, and its description of expected input parameter types. Also, if you enter `a=str`, that is fine in Python. But try entering `a = PyObject`. You get NameError. Can I say the following: `PyObject` is a c-type, used by c to define a Python class. But it is not a standard type *within Python*. – eric Dec 29 '14 at 06:23
  • 2
    @neuronet: That documentation breaks the abstraction between Python and its implementation. There is no actual negative side effect, but it can be confusing to read if you're not aware of the implementation details to begin with. – Ignacio Vazquez-Abrams Dec 29 '14 at 06:26