c
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
.
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 |
typedef | Parameter Types | Return Type |
---|---|---|
:callocfunc |
:c PyTypeObject *:c Py_ssize_t |
:cPyObject * |
:cdestructor |
:cPyObject * |
void |
:cfreefunc |
void * | void |
:ctraverseproc |
:c PyObject *:c visitproc void * |
int |
:cnewfunc |
:c PyObject *:c PyObject *:c PyObject * |
:cPyObject * |
:cinitproc |
:c PyObject *:c PyObject *:c PyObject * |
int |
:creprfunc |
:cPyObject * |
:cPyObject * |
:cgetattrfunc |
:c PyObject *const char * |
:cPyObject * |
:csetattrfunc |
:c PyObject *const char * :c PyObject * |
int |
:cgetattrofunc |
:c PyObject *:c PyObject * |
:cPyObject * |
:csetattrofunc |
:c PyObject *:c PyObject *:c PyObject * |
int |
:cdescrgetfunc |
:c PyObject *:c PyObject *:c PyObject * |
:cPyObject * |
:cdescrsetfunc |
:c PyObject *:c PyObject *:c PyObject * |
int |
:chashfunc |
:cPyObject * |
Py_hash_t |
:crichcmpfunc |
:c PyObject *:c PyObject *int |
:cPyObject * |
:cgetiterfunc |
:cPyObject * |
:cPyObject * |
:citernextfunc |
:cPyObject * |
:cPyObject * |
:clenfunc |
:cPyObject * |
:cPy_ssize_t |
:cgetbufferproc |
:c PyObject *:c Py_buffer *int |
int |
:creleasebufferproc |
:c PyObject *:c Py_buffer * |
void |
:cinquiry |
:cPyObject * |
int |
:cunaryfunc |
:c PyObject * |
:cPyObject * |
:cbinaryfunc |
:c PyObject *:c PyObject * |
:cPyObject * |
:cternaryfunc |
:c PyObject *:c PyObject *:c PyObject * |
:cPyObject * |
:cssizeargfunc |
:c PyObject *:c Py_ssize_t |
:cPyObject * |
:cssizeobjargproc |
:c PyObject *:c Py_ssize_t :c PyObject * |
int |
:cobjobjproc |
:c PyObject *:c PyObject * |
int |
:cobjobjargproc |
:c PyObject *:c PyObject *:c PyObject * |
int |
See slot-typedefs
below for more detail.
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
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.
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 isabs(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 :c
PyObject_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 thesizeof
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 ofdouble
. :c~PyTypeObject.tp_itemsize
issizeof(double)
. It is the programmer's responsibility that :c~PyTypeObject.tp_basicsize
is a multiple ofsizeof(double)
(assuming this is the alignment requirement fordouble
).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).
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.
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
.
Amaury Forgeot d'Arc
Amaury Forgeot d'Arc
Amaury Forgeot d'Arc
Greg J. Stein <greg@lyra.org>
Benjamin Peterson
Stefan Krah
Yury Selivanov <yselivanov@sprymix.com>
3.5
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 *),
};