Skip to content

Latest commit

 

History

History
2840 lines (2015 loc) · 130 KB

typeobj.rst

File metadata and controls

2840 lines (2015 loc) · 130 KB

c

Type Objects

Perhaps one of the most important structures of the Python object system is the structure that defines a new type: the :cPyTypeObject structure. Type objects can be handled using any of the PyObject_* or PyType_* functions, but do not offer much that's interesting to most Python applications. These objects are fundamental to how objects behave, so they are very important to the interpreter itself and to any extension module that implements new types.

Type objects are fairly large compared to most of the standard types. The reason for the size is that each type object stores a large number of values, mostly C function pointers, each of which implements a small part of the type's functionality. The fields of the type object are examined in detail in this section. The fields will be described in the order in which they occur in the structure.

In addition to the following quick reference, the typedef-examples section provides at-a-glance insight into the meaning and use of :cPyTypeObject.

Quick Reference

"tp slots"

sub-slots

Slot Type <slot-typedefs-table> special methods
:c~PyAsyncMethods.am_await :cunaryfunc __await__
:c~PyAsyncMethods.am_aiter :cunaryfunc __aiter__
:c~PyAsyncMethods.am_anext :cunaryfunc __anext__
:c~PyAsyncMethods.am_send :csendfunc
:c~PyNumberMethods.nb_add :cbinaryfunc __add__ __radd__
:c~PyNumberMethods.nb_inplace_add :cbinaryfunc __iadd__
:c~PyNumberMethods.nb_subtract :cbinaryfunc __sub__ __rsub__
:c~PyNumberMethods.nb_inplace_subtract :cbinaryfunc __isub__
:c~PyNumberMethods.nb_multiply :cbinaryfunc __mul__ __rmul__
:c~PyNumberMethods.nb_inplace_multiply :cbinaryfunc __imul__
:c~PyNumberMethods.nb_remainder :cbinaryfunc __mod__ __rmod__
:c~PyNumberMethods.nb_inplace_remainder :cbinaryfunc __imod__
:c~PyNumberMethods.nb_divmod :cbinaryfunc __divmod__ __rdivmod__
:c~PyNumberMethods.nb_power :cternaryfunc __pow__ __rpow__
:c~PyNumberMethods.nb_inplace_power :cternaryfunc __ipow__
:c~PyNumberMethods.nb_negative :cunaryfunc __neg__
:c~PyNumberMethods.nb_positive :cunaryfunc __pos__
:c~PyNumberMethods.nb_absolute :cunaryfunc __abs__
:c~PyNumberMethods.nb_bool :cinquiry __bool__
:c~PyNumberMethods.nb_invert :cunaryfunc __invert__
:c~PyNumberMethods.nb_lshift :cbinaryfunc __lshift__ __rlshift__
:c~PyNumberMethods.nb_inplace_lshift :cbinaryfunc __ilshift__
:c~PyNumberMethods.nb_rshift :cbinaryfunc __rshift__ __rrshift__
:c~PyNumberMethods.nb_inplace_rshift :cbinaryfunc __irshift__
:c~PyNumberMethods.nb_and :cbinaryfunc __and__ __rand__
:c~PyNumberMethods.nb_inplace_and :cbinaryfunc __iand__
:c~PyNumberMethods.nb_xor :cbinaryfunc __xor__ __rxor__
:c~PyNumberMethods.nb_inplace_xor :cbinaryfunc __ixor__
:c~PyNumberMethods.nb_or :cbinaryfunc __or__ __ror__
:c~PyNumberMethods.nb_inplace_or :cbinaryfunc __ior__
:c~PyNumberMethods.nb_int :cunaryfunc __int__
:c~PyNumberMethods.nb_reserved void *
:c~PyNumberMethods.nb_float :cunaryfunc __float__
:c~PyNumberMethods.nb_floor_divide :cbinaryfunc __floordiv__
:c~PyNumberMethods.nb_inplace_floor_divide :cbinaryfunc __ifloordiv__
:c~PyNumberMethods.nb_true_divide :cbinaryfunc __truediv__
:c~PyNumberMethods.nb_inplace_true_divide :cbinaryfunc __itruediv__
:c~PyNumberMethods.nb_index :cunaryfunc __index__
:c~PyNumberMethods.nb_matrix_multiply :cbinaryfunc __matmul__ __rmatmul__
:c~PyNumberMethods.nb_inplace_matrix_multiply :cbinaryfunc __imatmul__
:c~PyMappingMethods.mp_length :clenfunc __len__
:c~PyMappingMethods.mp_subscript :cbinaryfunc __getitem__
:c~PyMappingMethods.mp_ass_subscript :cobjobjargproc __setitem__, __delitem__
:c~PySequenceMethods.sq_length :clenfunc __len__
:c~PySequenceMethods.sq_concat :cbinaryfunc __add__
:c~PySequenceMethods.sq_repeat :cssizeargfunc __mul__
:c~PySequenceMethods.sq_item :cssizeargfunc __getitem__
:c~PySequenceMethods.sq_ass_item :cssizeobjargproc __setitem__ __delitem__
:c~PySequenceMethods.sq_contains :cobjobjproc __contains__
:c~PySequenceMethods.sq_inplace_concat :cbinaryfunc __iadd__
:c~PySequenceMethods.sq_inplace_repeat :cssizeargfunc __imul__
:c~PyBufferProcs.bf_getbuffer :cgetbufferproc
:c~PyBufferProcs.bf_releasebuffer :creleasebufferproc

slot typedefs

typedef Parameter Types Return Type
:callocfunc
:cPyTypeObject *
:cPy_ssize_t
:cPyObject *
:cdestructor :cPyObject * void
:cfreefunc void * void
:ctraverseproc
:cPyObject *
:cvisitproc
void *
int
:cnewfunc
:cPyObject *
:cPyObject *
:cPyObject *
:cPyObject *
:cinitproc
:cPyObject *
:cPyObject *
:cPyObject *
int
:creprfunc :cPyObject * :cPyObject *
:cgetattrfunc
:cPyObject *
const char *
:cPyObject *
:csetattrfunc
:cPyObject *
const char *
:cPyObject *
int
:cgetattrofunc
:cPyObject *
:cPyObject *
:cPyObject *
:csetattrofunc
:cPyObject *
:cPyObject *
:cPyObject *
int
:cdescrgetfunc
:cPyObject *
:cPyObject *
:cPyObject *
:cPyObject *
:cdescrsetfunc
:cPyObject *
:cPyObject *
:cPyObject *
int
:chashfunc :cPyObject * Py_hash_t
:crichcmpfunc
:cPyObject *
:cPyObject *
int
:cPyObject *
:cgetiterfunc :cPyObject * :cPyObject *
:citernextfunc :cPyObject * :cPyObject *
:clenfunc :cPyObject * :cPy_ssize_t
:cgetbufferproc
:cPyObject *
:cPy_buffer *
int
int
:creleasebufferproc
:cPyObject *
:cPy_buffer *
void
:cinquiry :cPyObject * int
:cunaryfunc
:cPyObject *
:cPyObject *
:cbinaryfunc
:cPyObject *
:cPyObject *
:cPyObject *
:cternaryfunc
:cPyObject *
:cPyObject *
:cPyObject *
:cPyObject *
:cssizeargfunc
:cPyObject *
:cPy_ssize_t
:cPyObject *
:cssizeobjargproc
:cPyObject *
:cPy_ssize_t
:cPyObject *
int
:cobjobjproc
:cPyObject *
:cPyObject *
int
:cobjobjargproc
:cPyObject *
:cPyObject *
:cPyObject *
int

See slot-typedefs below for more detail.

PyTypeObject Definition

The structure definition for :cPyTypeObject can be found in Include/object.h. For convenience of reference, this repeats the definition found there:

../includes/typestruct.h

PyObject Slots

The type object structure extends the :cPyVarObject structure. The :c~PyVarObject.ob_size field is used for dynamic types (created by :c!type_new, usually called from a class statement). Note that :cPyType_Type (the metatype) initializes :c~PyTypeObject.tp_itemsize, which means that its instances (i.e. type objects) must have the :c~PyVarObject.ob_size field.

PyVarObject Slots

PyTypeObject Slots

Each slot has a section describing inheritance. If :cPyType_Ready may set a value when the field is set to NULL then there will also be a "Default" section. (Note that many fields set on :cPyBaseObject_Type and :cPyType_Type effectively act as defaults.)

These fields allow calculating the size in bytes of instances of the type.

There are two kinds of types: types with fixed-length instances have a zero :c~PyTypeObject.tp_itemsize field, types with variable-length instances have a non-zero :c~PyTypeObject.tp_itemsize field. For a type with fixed-length instances, all instances have the same size, given in :c~PyTypeObject.tp_basicsize.

For a type with variable-length instances, the instances must have an :c~PyVarObject.ob_size field, and the instance size is :c~PyTypeObject.tp_basicsize plus N times :c~PyTypeObject.tp_itemsize, where N is the "length" of the object. The value of N is typically stored in the instance's :c~PyVarObject.ob_size field. There are exceptions: for example, ints use a negative :c~PyVarObject.ob_size to indicate a negative number, and N is abs(ob_size) there. Also, the presence of an :c~PyVarObject.ob_size field in the instance layout doesn't mean that the instance structure is variable-length (for example, the structure for the list type has fixed-length instances, yet those instances have a meaningful :c~PyVarObject.ob_size field).

The basic size includes the fields in the instance declared by the macro :cPyObject_HEAD or :cPyObject_VAR_HEAD (whichever is used to declare the instance struct) and this in turn includes the :c~PyObject._ob_prev and :c~PyObject._ob_next fields if they are present. This means that the only correct way to get an initializer for the :c~PyTypeObject.tp_basicsize is to use the sizeof operator on the struct used to declare the instance layout. The basic size does not include the GC header size.

A note about alignment: if the variable items require a particular alignment, this should be taken care of by the value of :c~PyTypeObject.tp_basicsize. Example: suppose a type implements an array of double. :c~PyTypeObject.tp_itemsize is sizeof(double). It is the programmer's responsibility that :c~PyTypeObject.tp_basicsize is a multiple of sizeof(double) (assuming this is the alignment requirement for double).

For any type with variable-length instances, this field must not be NULL.

Inheritance:

These fields are inherited separately by subtypes. If the base type has a non-zero :c~PyTypeObject.tp_itemsize, it is generally not safe to set :c~PyTypeObject.tp_itemsize to a different non-zero value in a subtype (though this depends on the implementation of the base type).

Static Types

Traditionally, types defined in C code are static, that is, a static :cPyTypeObject structure is defined directly in code and initialized using :cPyType_Ready.

This results in types that are limited relative to types defined in Python:

  • Static types are limited to one base, i.e. they cannot use multiple inheritance.
  • Static type objects (but not necessarily their instances) are immutable. It is not possible to add or modify the type object's attributes from Python.
  • Static type objects are shared across sub-interpreters <sub-interpreter-support>, so they should not include any subinterpreter-specific state.

Also, since :cPyTypeObject is only part of the Limited API <limited-c-api> as an opaque struct, any extension modules using static types must be compiled for a specific Python minor version.

Heap Types

An alternative to static types <static-types> is heap-allocated types, or heap types for short, which correspond closely to classes created by Python's class statement. Heap types have the :cPy_TPFLAGS_HEAPTYPE flag set.

This is done by filling a :cPyType_Spec structure and calling :cPyType_FromSpec, :cPyType_FromSpecWithBases, :cPyType_FromModuleAndSpec, or :cPyType_FromMetaclass.

Number Object Structures

Amaury Forgeot d'Arc

Mapping Object Structures

Amaury Forgeot d'Arc

Sequence Object Structures

Amaury Forgeot d'Arc

Buffer Object Structures

Greg J. Stein <greg@lyra.org>

Benjamin Peterson

Stefan Krah

Async Object Structures

Yury Selivanov <yselivanov@sprymix.com>

3.5

Slot Type typedefs

Examples

The following are simple examples of Python type definitions. They include common usage you may encounter. Some demonstrate tricky corner cases. For more examples, practical info, and a tutorial, see defining-new-types and new-types-topics.

A basic static type <static-types>:

typedef struct {
    PyObject_HEAD
    const char *data;
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject),
    .tp_doc = PyDoc_STR("My objects"),
    .tp_new = myobj_new,
    .tp_dealloc = (destructor)myobj_dealloc,
    .tp_repr = (reprfunc)myobj_repr,
};

You may also find older code (especially in the CPython code base) with a more verbose initializer:

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    "mymod.MyObject",               /* tp_name */
    sizeof(MyObject),               /* tp_basicsize */
    0,                              /* tp_itemsize */
    (destructor)myobj_dealloc,      /* tp_dealloc */
    0,                              /* tp_vectorcall_offset */
    0,                              /* tp_getattr */
    0,                              /* tp_setattr */
    0,                              /* tp_as_async */
    (reprfunc)myobj_repr,           /* tp_repr */
    0,                              /* tp_as_number */
    0,                              /* tp_as_sequence */
    0,                              /* tp_as_mapping */
    0,                              /* tp_hash */
    0,                              /* tp_call */
    0,                              /* tp_str */
    0,                              /* tp_getattro */
    0,                              /* tp_setattro */
    0,                              /* tp_as_buffer */
    0,                              /* tp_flags */
    PyDoc_STR("My objects"),        /* tp_doc */
    0,                              /* tp_traverse */
    0,                              /* tp_clear */
    0,                              /* tp_richcompare */
    0,                              /* tp_weaklistoffset */
    0,                              /* tp_iter */
    0,                              /* tp_iternext */
    0,                              /* tp_methods */
    0,                              /* tp_members */
    0,                              /* tp_getset */
    0,                              /* tp_base */
    0,                              /* tp_dict */
    0,                              /* tp_descr_get */
    0,                              /* tp_descr_set */
    0,                              /* tp_dictoffset */
    0,                              /* tp_init */
    0,                              /* tp_alloc */
    myobj_new,                      /* tp_new */
};

A type that supports weakrefs, instance dicts, and hashing:

typedef struct {
    PyObject_HEAD
    const char *data;
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject),
    .tp_doc = PyDoc_STR("My objects"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
         Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT |
         Py_TPFLAGS_MANAGED_WEAKREF,
    .tp_new = myobj_new,
    .tp_traverse = (traverseproc)myobj_traverse,
    .tp_clear = (inquiry)myobj_clear,
    .tp_alloc = PyType_GenericNew,
    .tp_dealloc = (destructor)myobj_dealloc,
    .tp_repr = (reprfunc)myobj_repr,
    .tp_hash = (hashfunc)myobj_hash,
    .tp_richcompare = PyBaseObject_Type.tp_richcompare,
};

A str subclass that cannot be subclassed and cannot be called to create instances (e.g. uses a separate factory func) using :cPy_TPFLAGS_DISALLOW_INSTANTIATION flag:

typedef struct {
    PyUnicodeObject raw;
    char *extra;
} MyStr;

static PyTypeObject MyStr_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyStr",
    .tp_basicsize = sizeof(MyStr),
    .tp_base = NULL,  // set to &PyUnicode_Type in module init
    .tp_doc = PyDoc_STR("my custom str"),
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
    .tp_repr = (reprfunc)myobj_repr,
};

The simplest static type <static-types> with fixed-length instances:

typedef struct {
    PyObject_HEAD
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
};

The simplest static type <static-types> with variable-length instances:

typedef struct {
    PyObject_VAR_HEAD
    const char *data[1];
} MyObject;

static PyTypeObject MyObject_Type = {
    PyVarObject_HEAD_INIT(NULL, 0)
    .tp_name = "mymod.MyObject",
    .tp_basicsize = sizeof(MyObject) - sizeof(char *),
    .tp_itemsize = sizeof(char *),
};