Type Object Structures¶
Perhaps one of the most important structures of the Python object system is the
structure that defines a new type: the PyTypeObject 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 Examples
section provides at-a-glance insight into the meaning and use of
PyTypeObject.
Quick Reference¶
“tp slots”¶
PyTypeObject Slot [1] |
special methods/attrs |
Info [2] |
||||
|---|---|---|---|---|---|---|
O |
T |
D |
I |
|||
<R> |
const char * |
__name__ |
X |
X |
||
X |
X |
X |
||||
X |
X |
|||||
X |
X |
X |
||||
X |
X |
|||||
__getattribute__, __getattr__ |
G |
|||||
__setattr__, __delattr__ |
G |
|||||
% |
||||||
__repr__ |
X |
X |
X |
|||
% |
||||||
% |
||||||
% |
||||||
__hash__ |
X |
G |
||||
__call__ |
X |
X |
||||
__str__ |
X |
X |
||||
__getattribute__, __getattr__ |
X |
X |
G |
|||
__setattr__, __delattr__ |
X |
X |
G |
|||
% |
||||||
unsigned long |
X |
X |
? |
|||
const char * |
__doc__ |
X |
X |
|||
X |
G |
|||||
X |
G |
|||||
__lt__, __le__, __eq__, __ne__, __gt__, __ge__ |
X |
G |
||||
X |
? |
|||||
__iter__ |
X |
|||||
__next__ |
X |
|||||
|
X |
X |
||||
|
X |
|||||
|
X |
X |
||||
__base__ |
X |
|||||
|
__dict__ |
? |
||||
__get__ |
X |
|||||
__set__, __delete__ |
X |
|||||
X |
? |
|||||
__init__ |
X |
X |
X |
|||
X |
? |
? |
||||
__new__ |
X |
X |
? |
? |
||
X |
X |
? |
? |
|||
X |
X |
|||||
< |
|
__bases__ |
~ |
|||
< |
|
__mro__ |
~ |
|||
[ |
|
|||||
void * |
__subclasses__ |
|||||
|
||||||
( |
||||||
unsigned int |
||||||
__del__ |
X |
|||||
unsigned char |
||||||
sub-slots¶
Slot |
special methods |
|
|---|---|---|
__await__ |
||
__aiter__ |
||
__anext__ |
||
__add__ __radd__ |
||
__iadd__ |
||
__sub__ __rsub__ |
||
__isub__ |
||
__mul__ __rmul__ |
||
__imul__ |
||
__mod__ __rmod__ |
||
__imod__ |
||
__divmod__ __rdivmod__ |
||
__pow__ __rpow__ |
||
__ipow__ |
||
__neg__ |
||
__pos__ |
||
__abs__ |
||
__bool__ |
||
__invert__ |
||
__lshift__ __rlshift__ |
||
__ilshift__ |
||
__rshift__ __rrshift__ |
||
__irshift__ |
||
__and__ __rand__ |
||
__iand__ |
||
__xor__ __rxor__ |
||
__ixor__ |
||
__or__ __ror__ |
||
__ior__ |
||
__int__ |
||
void * |
||
__float__ |
||
__floordiv__ |
||
__ifloordiv__ |
||
__truediv__ |
||
__itruediv__ |
||
__index__ |
||
__matmul__ __rmatmul__ |
||
__imatmul__ |
||
__len__ |
||
__getitem__ |
||
__setitem__, __delitem__ |
||
__len__ |
||
__add__ |
||
__mul__ |
||
__getitem__ |
||
__setitem__ __delitem__ |
||
__contains__ |
||
__iadd__ |
||
__imul__ |
||
__buffer__ |
||
__release_buffer__ |
||
slot typedefs¶
typedef |
Parameter Types |
Return Type |
|---|---|---|
|
||
|
void |
|
void * |
void |
|
int |
||
|
||
int |
||
|
|
|
PyObject *const char *
|
|
|
int |
||
|
||
int |
||
|
||
int |
||
|
Py_hash_t |
|
|
||
|
|
|
|
|
|
|
||
int |
||
void |
||
|
int |
|
PyObject * |
|
|
|
||
|
||
|
||
int |
||
int |
||
int |
See Slot Type typedefs below for more detail.
PyTypeObject Definition¶
The structure definition for PyTypeObject can be found in
Include/cpython/object.h. For convenience of reference, this repeats the
definition found there:
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; /* For printing, in format "<module>.<name>" */
Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
Py_ssize_t tp_vectorcall_offset;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)
or tp_reserved (Python 3) */
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
unsigned long tp_flags;
const char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
PyMethodDef *tp_methods;
PyMemberDef *tp_members;
PyGetSetDef *tp_getset;
// Strong reference on a heap type, borrowed reference on a static type
PyTypeObject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
Py_ssize_t tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache; /* no longer used */
void *tp_subclasses; /* for static builtin types this is an index */
PyObject *tp_weaklist; /* not used for static builtin types */
destructor tp_del;
/* Type attribute cache version tag. Added in version 2.6.
* If zero, the cache is invalid and must be initialized.
*/
unsigned int tp_version_tag;
destructor tp_finalize;
vectorcallfunc tp_vectorcall;
/* bitset of which type-watchers care about this type */
unsigned char tp_watched;
/* Number of tp_version_tag values used.
* Set to _Py_ATTR_CACHE_UNUSED if the attribute cache is
* disabled for this type (e.g. due to custom MRO entries).
* Otherwise, limited to MAX_VERSIONS_PER_CLASS (defined elsewhere).
*/
uint16_t tp_versions_used;
} PyTypeObject;
PyObject Slots¶
The type object structure extends the PyVarObject structure. The
ob_size field is used for dynamic types (created by type_new(),
usually called from a class statement). Note that PyType_Type (the
metatype) initializes tp_itemsize, which means that its instances (i.e.
type objects) must have the ob_size field.
The type object’s reference count is initialized to
1by thePyObject_HEAD_INITmacro. Note that for statically allocated type objects, the type’s instances (objects whoseob_typepoints back to the type) do not count as references. But for dynamically allocated type objects, the instances do count as references.Inheritance:
This field is not inherited by subtypes.
This is the type’s type, in other words its metatype. It is initialized by the argument to the
PyObject_HEAD_INITmacro, and its value should normally be&PyType_Type. However, for dynamically loadable extension modules that must be usable on Windows (at least), the compiler complains that this is not a valid initializer. Therefore, the convention is to passNULLto thePyObject_HEAD_INITmacro and to initialize this field explicitly at the start of the module’s initialization function, before doing anything else. This is typically done like this:Foo_Type.ob_type = &PyType_Type;This should be done before any instances of the type are created.
PyType_Ready()checks ifob_typeisNULL, and if so, initializes it to theob_typefield of the base class.PyType_Ready()will not change this field if it is non-zero.Inheritance:
This field is inherited by subtypes.
PyVarObject Slots¶
For statically allocated type objects, this should be initialized to zero. For dynamically allocated type objects, this field has a special internal meaning.
This field should be accessed using the
Py_SIZE()macro.Inheritance:
This field is not inherited by subtypes.
PyTypeObject Slots¶
Each slot has a section describing inheritance. If PyType_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 PyBaseObject_Type
and PyType_Type effectively act as defaults.)
-
const char *PyTypeObject.tp_name¶
See
Py_tp_namefor the correspondingSlot ID.Pointer to a NUL-terminated string containing the name of the type. For types that are accessible as module globals, the string should be the full module name, followed by a dot, followed by the type name; for built-in types, it should be just the type name. If the module is a submodule of a package, the full package name is part of the full module name. For example, a type named
Tdefined in moduleMin subpackageQin packagePshould have thetp_nameinitializer"P.Q.M.T".For dynamically allocated type objects, this should just be the type name, and the module name explicitly stored in the type dict as the value for key
'__module__'.For statically allocated type objects, the tp_name field should contain a dot. Everything before the last dot is made accessible as the
__module__attribute, and everything after the last dot is made accessible as the__name__attribute.If no dot is present, the entire
tp_namefield is made accessible as the__name__attribute, and the__module__attribute is undefined (unless explicitly set in the dictionary, as explained above). This means your type will be impossible to pickle. Additionally, it will not be listed in module documentations created with pydoc.This field must not be
NULL. It is the only required field inPyTypeObject()(other than potentiallytp_itemsize).Inheritance:
This field is not inherited by subtypes.
-
Py_ssize_t PyTypeObject.tp_basicsize¶
-
Py_ssize_t PyTypeObject.tp_itemsize¶
These fields allow calculating the size in bytes of instances of the type.
See
Py_tp_basicsize,Py_tp_extra_basicsizeandPy_tp_itemsizefor the correspondingSlot IDs.There are two kinds of types: types with fixed-length instances have a zero
tp_itemsizefield, types with variable-length instances have a non-zerotp_itemsizefield. For a type with fixed-length instances, all instances have the same size, given intp_basicsize. (Exceptions to this rule can be made usingPyUnstable_Object_GC_NewWithExtraData().)For a type with variable-length instances, the instances must have an
ob_sizefield, and the instance size istp_basicsizeplus N timestp_itemsize, where N is the “length” of the object.Functions like
PyObject_NewVar()will take the value of N as an argument, and store in the instance’sob_sizefield. Note that theob_sizefield may later be used for other purposes. For example,intinstances use the bits ofob_sizein an implementation-defined way; the underlying storage and its size should be accessed usingPyLong_Export().Note
The
ob_sizefield should be accessed using thePy_SIZE()andPy_SET_SIZE()macros.Also, the presence of an
ob_sizefield in the instance layout doesn’t mean that the instance structure is variable-length. For example, thelisttype has fixed-length instances, yet those instances have aob_sizefield. (As withint, avoid reading lists’ob_sizedirectly. CallPyList_Size()instead.)The
tp_basicsizeincludes size needed for data of the type’stp_base, plus any extra data needed by each instance.The correct way to set
tp_basicsizeis to use thesizeofoperator on the struct used to declare the instance layout. This struct must include the struct used to declare the base type. In other words,tp_basicsizemust be greater than or equal to the base’stp_basicsize.Since every type is a subtype of
object, this struct must includePyObjectorPyVarObject(depending on whetherob_sizeshould be included). These are usually defined by the macroPyObject_HEADorPyObject_VAR_HEAD, respectively.The basic size does not include the GC header size, as that header is not part of
PyObject_HEAD.For cases where struct used to declare the base type is unknown, see
PyType_Spec.basicsizeandPyType_FromMetaclass().Notes about alignment:
tp_basicsizemust be a multiple of_Alignof(PyObject). When usingsizeofon astructthat includesPyObject_HEAD, as recommended, the compiler ensures this. When not using a Cstruct, or when using compiler extensions like__attribute__((packed)), it is up to you.If the variable items require a particular alignment,
tp_basicsizeandtp_itemsizemust each be a multiple of that alignment. For example, if a type’s variable part stores adouble, it is your responsibility that both fields are a multiple of_Alignof(double).
Inheritance:
These fields are inherited separately by subtypes. (That is, if the field is set to zero,
PyType_Ready()will copy the value from the base type, indicating that the instances do not need additional storage.)If the base type has a non-zero
tp_itemsize, it is generally not safe to settp_itemsizeto a different non-zero value in a subtype (though this depends on the implementation of the base type).
-
destructor PyTypeObject.tp_dealloc¶
The corresponding slot ID
Py_tp_deallocis part of the Stable ABI.A pointer to the instance destructor function. The function signature is:
void tp_dealloc(PyObject *self);
The destructor function should remove all references which the instance owns (e.g., call
Py_CLEAR()), free all memory buffers owned by the instance, and call the type’stp_freefunction to free the object itself.If you may call functions that may set the error indicator, you must use
PyErr_GetRaisedException()andPyErr_SetRaisedException()to ensure you don’t clobber a preexisting error indicator (the deallocation could have occurred while processing a different error):static void foo_dealloc(foo_object *self) { PyObject *et, *ev, *etb; PyObject *exc = PyErr_GetRaisedException(); ... PyErr_SetRaisedException(exc); }
The dealloc handler itself must not raise an exception; if it hits an error case it should call
PyErr_FormatUnraisable()to log (and clear) an unraisable exception.No guarantees are made about when an object is destroyed, except:
Python will destroy an object immediately or some time after the final reference to the object is deleted, unless its finalizer (
tp_finalize) subsequently resurrects the object.An object will not be destroyed while it is being automatically finalized (
tp_finalize) or automatically cleared (tp_clear).
CPython currently destroys an object immediately from
Py_DECREF()when the new reference count is zero, but this may change in a future version.It is recommended to call
PyObject_CallFinalizerFromDealloc()at the beginning oftp_deallocto guarantee that the object is always finalized before destruction.If the type supports garbage collection (the
Py_TPFLAGS_HAVE_GCflag is set), the destructor should callPyObject_GC_UnTrack()before clearing any member fields.It is permissible to call
tp_clearfromtp_deallocto reduce code duplication and to guarantee that the object is always cleared before destruction. Beware thattp_clearmight have already been called.If the type is heap allocated (
Py_TPFLAGS_HEAPTYPE), the deallocator should release the owned reference to its type object (viaPy_DECREF()) after calling the type deallocator. See the example code below.:static void foo_dealloc(PyObject *op) { foo_object *self = (foo_object *) op; PyObject_GC_UnTrack(self); Py_CLEAR(self->ref); Py_TYPE(self)->tp_free(self); }
tp_deallocmust leave the exception status unchanged. If it needs to call something that might raise an exception, the exception state must be backed up first and restored later (after logging any exceptions withPyErr_WriteUnraisable()).Example:
static void foo_dealloc(PyObject *self) { PyObject *exc = PyErr_GetRaisedException(); if (PyObject_CallFinalizerFromDealloc(self) < 0) { // self was resurrected. goto done; } PyTypeObject *tp = Py_TYPE(self); if (tp->tp_flags & Py_TPFLAGS_HAVE_GC) { PyObject_GC_UnTrack(self); } // Optional, but convenient to avoid code duplication. if (tp->tp_clear && tp->tp_clear(self) < 0) { PyErr_WriteUnraisable(self); } // Any additional destruction goes here. tp->tp_free(self); self = NULL; // In case PyErr_WriteUnraisable() is called below. if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_CLEAR(tp); } done: // Optional, if something was called that might have raised an // exception. if (PyErr_Occurred()) { PyErr_WriteUnraisable(self); } PyErr_SetRaisedException(exc); }
tp_deallocmay be called from any Python thread, not just the thread which created the object (if the object becomes part of a refcount cycle, that cycle might be collected by a garbage collection on any thread). This is not a problem for Python API calls, since the thread on whichtp_deallocis called with an attached thread state. However, if the object being destroyed in turn destroys objects from some other C library, care should be taken to ensure that destroying those objects on the thread which calledtp_deallocwill not violate any assumptions of the library.Inheritance:
This field is inherited by subtypes.
See also
Object Life Cycle for details about how this slot relates to other slots.
-
Py_ssize_t PyTypeObject.tp_vectorcall_offset¶
An optional offset to a per-instance function that implements calling the object using the vectorcall protocol, a more efficient alternative of the simpler
tp_call.This field is only used if the flag
Py_TPFLAGS_HAVE_VECTORCALLis set. If so, this must be a positive integer containing the offset in the instance of avectorcallfuncpointer.The vectorcallfunc pointer may be
NULL, in which case the instance behaves as ifPy_TPFLAGS_HAVE_VECTORCALLwas not set: calling the instance falls back totp_call.Any class that sets
Py_TPFLAGS_HAVE_VECTORCALLmust also settp_calland make sure its behaviour is consistent with the vectorcallfunc function. This can be done by setting tp_call toPyVectorcall_Call().Changed in version 3.8: Before version 3.8, this slot was named
tp_print. In Python 2.x, it was used for printing to a file. In Python 3.0 to 3.7, it was unused.Changed in version 3.12: Before version 3.12, it was not recommended for mutable heap types to implement the vectorcall protocol. When a user sets
__call__in Python code, only tp_call is updated, likely making it inconsistent with the vectorcall function. Since 3.12, setting__call__will disable vectorcall optimization by clearing thePy_TPFLAGS_HAVE_VECTORCALLflag.Inheritance:
This field is always inherited. However, the
Py_TPFLAGS_HAVE_VECTORCALLflag is not always inherited. If it’s not set, then the subclass won’t use vectorcall, except whenPyVectorcall_Call()is explicitly called.
-
getattrfunc PyTypeObject.tp_getattr¶
The corresponding slot ID
Py_tp_getattris part of the Stable ABI.An optional pointer to the get-attribute-string function.
This field is deprecated. When it is defined, it should point to a function that acts the same as the
tp_getattrofunction, but taking a C string instead of a Python string object to give the attribute name.Inheritance:
Group:
tp_getattr,tp_getattroThis field is inherited by subtypes together with
tp_getattro: a subtype inherits bothtp_getattrandtp_getattrofrom its base type when the subtype’stp_getattrandtp_getattroare bothNULL.
-
setattrfunc PyTypeObject.tp_setattr¶
The corresponding slot ID
Py_tp_setattris part of the Stable ABI.An optional pointer to the function for setting and deleting attributes.
This field is deprecated. When it is defined, it should point to a function that acts the same as the
tp_setattrofunction, but taking a C string instead of a Python string object to give the attribute name.Inheritance:
Group:
tp_setattr,tp_setattroThis field is inherited by subtypes together with
tp_setattro: a subtype inherits bothtp_setattrandtp_setattrofrom its base type when the subtype’stp_setattrandtp_setattroare bothNULL.
-
PyAsyncMethods *PyTypeObject.tp_as_async¶
Pointer to an additional structure that contains fields relevant only to objects which implement awaitable and asynchronous iterator protocols at the C-level. See Async Object Structures for details.
Added in version 3.5: Formerly known as
tp_compareandtp_reserved.Inheritance:
The
tp_as_asyncfield is not inherited, but the contained fields are inherited individually.