Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3: How can object be instance of type?

In Python 3, object is an instance of type and type is also an instance of object!

How is it possible that each class is derived from the other?

Any implementation details?

I checked this using isinstance(sub, base), which, according to Python documentation, checks if sub class is derived from base class:

isinstance(object, type)
Out[1]: True

isinstance(type, object)
Out[2]: True
like image 578
Mani Kanth Avatar asked Aug 13 '15 18:08

Mani Kanth


1 Answers

This is one of the edge cases in Python:

  • Everything in Python is an object, so since object is the base type of everything, type (being something in Python) is an instance of object.
  • Since object is the base type of everything, object is also a type, which makes object an instance of type.

Note that this relationship is nothing you can replicate with your own things in Python. It’s a single exception that is built into the language.


On the implementation side, the two names are represented by PyBaseObject_Type (for object) and PyType_Type (for type).

When you use isinstance, the type check—in the very last step, after everything else has failed—is done by type_is_subtype_base_chain:

type_is_subtype_base_chain(PyTypeObject *a, PyTypeObject *b)
{
    do {
        if (a == b)
            return 1;
        a = a->tp_base;
    } while (a != NULL);

    return (b == &PyBaseObject_Type);
}

This essentially keeps going up the type hierarchy of a and checks the resulting type against b. If it cannot find one, then the last resort is to check whether b is actually object in which case the function returns true: since everything is an object. So the “everything is an instance of object” part is actually hardcoded into the instance check.

And as for why object is a type, this is actually even simpler because it’s simply defined that way in the declaration of PyBaseObject_Type:

PyTypeObject PyBaseObject_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "object",                                   /* tp_name */
    sizeof(PyObject),                           /* tp_basicsize */
    …

The PyVarObject_HEAD_INIT essentially sets the core type information stuff, including the base type, which is PyType_Type.

There are actually two more consequences of this relationship:

  • Since everything is an object, object is also an instance of object: isinstance(object, object)
  • Since PyType_Type is also implemented with the same PyVarObject_HEAD_INIT, type is also a type: isinstance(type, type).
like image 198
poke Avatar answered Oct 08 '22 01:10

poke