CPython’s PyTypeObject

CPython includes a powerful C-API by which you can heavily customize Python. This includes creating custom types. Though you can create new types directly in Python now, this wasn’t always the case. Python has a strong heritage of tapping into C to produce new types. One consequence is that creating new Python types in C affords you more functionality than you’ll find in pure Python.

In this reference page we’ll be looking at the details surrounding PyTypeObject, which is the linchpin of Python types written in C.

The CPython C-API

One important thing to note is that CPython’s C-API provides a number of interfaces for efficiently interacting with Python objects in C. Those functions fall into one of two groups:

  • the abstract object API (e.g. PyObject_*)
  • the concrete object API (e.g. PyDict_*)

The concrete APIs take advantage of the implementation details of their respective types to get improved efficiency and functionality. However, this comes at the cost of ignoring implementations in subtypes. The dict concrete API is a prime example of this, as it make direct calls to static methods in the implementation, skipping a lookup of the relevant implementation on the type. This situation likely won’t change anytime soon due to the challenge of accommodating subtypes without damaging performance or functionality.

PyTypeObject, the Base Type Struct

The PyTypeObject, exposed in Python as type, is the cornerstone of the type system implementation in CPython.

Note: A “dynamic” type is one created through the class statement in Python (i.e. by calling type(), or some other metaclass).

Creating a Python Type in C

Defining a Python type in C involves populating the fields of a PyTypeObject struct with the values you care about. We call each of those fields a “slot”.

One the definition is ready, we pass it into the PyType_Ready() function, which does a number of things, inclulding exposing most of the type definition to Python’s attribute lookup mechanism.

PyTypeObject Slots

If a slot is not required it can be set to NULL.

Here is a table of the slots described in the docs [2]. It does not include the slots provided by PyObject_VAR_HEAD, etc., nor those added onto the end for the COUNT_ALLOCS macro.

Legend: * A slot name in parentheses means is is reserved or deprecated. * The “Req” column indicates that the slot is required. * The “Inh” column indicates that the slot is inherited by subclasses. * The “Rdy” column indicates that the slot is populated by PyType_Ready(). * The “Mem” column indicates that the slot is memory-management-related. * For each of these columns, “X” indicates an affirmative. * For “Req”, “T” means it may be ignored for types that never be deallocated (a rare case). * For “Rdy”, “U”means it’s used by PyType_Ready().

PyTypeObject Slot R e q R d y M e m Description
tp_name X     The class’s name, possibly fully qualified.
tp_basicsize X   X Base memory size of instances.
tp_itemsize     X Per-item size, if any.
tp_dealloc T   X Instance memory deallocator.
(tp_print)       Special stringification for writing to real files.
(tp_getattr)       tp_getattro using strings.
(tp_setattr)       tp_setattro using strings.
(tp_reserved)       (Was tp_compare.)
tp_repr       User-friendly representation.
tp_as_number   U   See PyNumberMethods.
tp_as_sequence   U   See PySequenceMethods.
tp_as_mapping   U   See PyMappingMethods.
tp_hash       Get the hash of an instance.
tp_call       “Run” an instance.
tp_str       Stringify an instance.
tp_getattro       Get an attribute’s value.
tp_setattro       Set an attribute’s value or remove the attribute.
tp_as_buffer   U   See PyBufferProcs.
tp_flags   X   A bit mask of various flags.
tp_doc       The class’s docstring.
tp_traverse     X GC helper for detecting cycles.
tp_clear     X GC helper for breaking cycles.
tp_richcompare       Same as the old __cmp__().
tp_weaklistoffset   U   Offset into instance struct for a list of weak refs.
tp_iter       Get an iterator for an instance.
tp_iternext       Iterate an instance.
tp_methods   U   Regular methods of the type.
tp_members   U   Regular data attributes.
tp_getset   U   The same as properties.
tp_base   U   The base type for inheritance.
tp_dict   X   The class’s dict, if any.
tp_descr_get       __get__ for the class.
tp_descr_set       __set__ & __del__ for the class.
tp_dictoffset   U   Offset into instance struct for instance namespace.
tp_init       Initialize an instance.
tp_alloc     X Get memory block for an instance.
tp_new       Return a new instance.
tp_free     X Release memory block for an obj.
tp_is_gc     X For when Py_TPFLAGS_HAVE_GC isn’t good enough.
tp_bases   X   Tuple of bases classes. (dynamic type only)
tp_mro   X   Calculated MRO tuple.
tp_cache   X   (Not used.)
tp_subclasses   X   List of weak refs to subclasses.
tp_weaklist   X   List of weak refs to the type.
tp_del       Deletion-time instance handling.

Note: None of the slots populated by PyType_Ready() should be set when defining a type, except for tp_flags.

Note: various flag bits in tp_flags may cause certain slots to be ignored.

Note: tp_print is effectively deprecated, so don’t use it.

Note: PyType_Ready() will build the new type with consideration for the various inherited slots. Thus, it effectively makes use of those slots.

Inheritance

Python types written in C still enjoy inheritance, but it’s a little different than in Python. For one thing, only single-inheritance is supported at the C level. For another, at the C level PyTypeReady facilitates a form of inheritance-by-copy. This is where inherited values are actually copied into the subclass.

Attribute lookup works the same either way, however. This means that values which PyType_Ready did not copy into the subclass are still available as long as they are exposed vi the base class’s __dict__.

Here’s a look at how inheritance-by-copy works for the various PyTypeObject slots:

Legend: * The “Inh” column is more complicated:

"*": not inherited but the value's items are.
"?": contained values *may* be inherited.
  • The “Grp” column indicates inheritance dependencies:

    <N>: not inherited unless all matching slots are NULL.
    
PyTypeObject Slot I n h G r p Notes
tp_name      
tp_basicsize X    
tp_itemsize X    
tp_dealloc X    
(tp_print) X    
(tp_getattr) X 1  
(tp_setattr) X 2  
(tp_reserved)      
tp_repr X    
tp_as_number
   
tp_as_sequence
   
tp_as_mapping
   
tp_hash X 3  
tp_call X    
tp_str X    
tp_getattro X 1  
tp_setattro X 2  
tp_as_buffer
   
tp_flags ? 4  
tp_doc      
tp_traverse X 4  
tp_clear X 4  
tp_richcompare X 3  
tp_weaklistoffset X    
tp_iter X    
tp_iternext X    
tp_methods     available through attr lookup
tp_members     available through attr lookup
tp_getset     available through attr lookup
tp_base      
tp_dict     available through attr lookup
tp_descr_get X    
tp_descr_set X    
tp_dictoffset X    
tp_init X    
tp_alloc ?   static types only
tp_new ?   not static subtypes with the default tp_base
tp_free ?   static types only
tp_is_gc X    
tp_bases      
tp_mro      
tp_cache      
tp_subclasses      
tp_weaklist      
tp_del x    

Note: Group 4 depends on the Py_TPFLAGS_HAVE_GC flag bit in tp_flags.

Defaults

A number of the PyTypeObject slots have default values, either by inheritance or by explicit setting (PyType_Ready). Here is a breakdown of what slots have defaults, where they come from, and what those values are:

PyTypeObject Slot Default Source Value
tp_name  
tp_basicsize PyBaseObject_Type.tp_basicsize sizeof(PyObject)
tp_itemsize  
tp_dealloc PyBaseObject_Type.tp_dealloc object_dealloc
(tp_print)  
(tp_getattr)  
(tp_setattr)  
(tp_reserved)  
tp_repr PyBaseObject_Type.tp_repr object_repr
tp_as_number  
tp_as_sequence  
tp_as_mapping  
tp_hash PyBaseObject_Type.tp_hash _Py_HashPointer
tp_call  
tp_str PyBaseObject_Type.tp_str object_str
tp_getattro PyBaseObject_Type.tp_getattro PyObj_GenericGetAttr
tp_setattro PyBaseObject_Type.tp_setattro PyObj_GenericSetAttr
tp_as_buffer  
tp_flags PyBaseObject_Type.tp_flags Py_TPFLAGS_DEFAULT Py_TPFLAGS_BASETYPE
tp_doc  
tp_traverse  
tp_clear  
tp_richcompare PyBaseObject_Type.tp_richcompare object_richcompare
tp_weaklistoffset  
tp_iter  
tp_iternext  
tp_methods  
tp_members  
tp_getset  
tp_base call to PyType_Ready PyBaseObject_Type
tp_dict  
tp_descr_get  
tp_descr_set  
tp_dictoffset  
tp_init PyBaseObject_Type.tp_init object_init
tp_alloc (st) PyBaseObject_Type.tp_alloc (dyn) call to type.__new__ PyType_GenericAlloc PyType_GenericAlloc
tp_new PyBaseObject_Type.tp_new object_new
tp_free (st) PyBaseObject_Type.tp_free (dyn) call to type.__new__ PyObject_Del <compatible f>
tp_is_gc  
tp_bases  
tp_mro  
tp_cache  
tp_subclasses  
tp_weaklist  
tp_del  

PyTypeObject Slot Types

Naturally each slot has a type. Some of the slots have a normal int/ long/pointer type. However, most of them have function pointers. Each of these function “types” (e.g. reprfunc) is actually a macro for a particular function pointer cast.

Consequently, each function you set in your type definition must be cast using that macro:

PyTypeObject MyType = {
    ...
    (reprfunc)my_repr,                  /* tp_repr */
    ...
};

For each of those slots the following table indicates the function’s parameters and return type. For non-function slots, just the slot’s type is populated and “—” is found in the parameters column.

For functions that return a PyObject *, it’s always a new reference. For functions that store a value (like tp_getattr), the value is never “borrowed”.

Note: visitproc is a function that takes PyObject * and returns int.

PyTypeObject Slot Type Parameter Types Return Type
tp_name char *  
tp_basicsize int  
tp_itemsize int  
tp_dealloc destructor <localobject> * void
tp_print printfunc PyObject * FILE * int int
(tp_getattr) getattrfunc PyObject * const char * PyObject *
(tp_setattr) setattrfunc PyObject * const char * PyObject * int
(tp_reserved) void*  
tp_repr reprfunc PyObject * PyObject *
tp_as_number PyNumberMethods *  
tp_as_sequence PySequenceMethods *  
tp_as_mapping PyMappingMethods *  
tp_hash hashfunc PyObject * Py_hash_t
tp_call ternaryfunc PyObject * PyObject * PyObject * PyObject *
tp_str reprfunc PyObject * PyObject *
tp_getattro getattrofunc PyObject * PyObject * PyObject *
tp_setattro setattrofunc PyObject * PyObject * PyObject * int
tp_as_buffer PyBufferProcs *  
tp_flags long  
tp_doc char *  
tp_traverse traverseproc <localobject> * “visitproc” void * int
tp_clear inquiry <localobject> * int
tp_richcompare richcmpfunc PyObject * PyObject * int PyObject *
tp_weaklistoffset long  
tp_iter getiterfunc PyObject * PyObject *
tp_iternext iternextfunc PyObject * PyObject *
tp_methods PyMethodDef[]  
tp_members PyMemberDef[]  
tp_getset PyGetSetDef[]  
tp_base PyTypeObject *  
tp_dict PyObject *  
tp_descr_get descrgetfunc PyObject * PyObject * PyObject * PyObject *
tp_descr_set descrsetfunc PyObject * PyObject * PyObject * int
tp_dictoffset long  
tp_init initproc PyObject * PyObject * PyObject * int
tp_alloc allocfunc PyTypeObject * Py_ssize_t PyObject *
tp_new newfunc PyTypeObject * PyObject * PyObject * PyObject *
tp_free freefunc void * void
tp_is_gc inquiry void * int
tp_bases PyObject *  
tp_mro PyObject *  
tp_cache PyObject *  
tp_subclasses PyObject *  
tp_weaklist PyObject *  
tp_del destructor PyObject * int

Helper functions/macros:

  • sizeof() - use to calculate tp_basicsize
  • PyDoc_STRVAR - preps a string for tp_doc

Specialized Slot Types

Some of the PyTypeObject slots are themselves structs. This way the main struct doesn’t have to get bigger than it already is. Also, types that don’t need the extra slots don’t need to take up as much memory.

PyNumberMethods Slot Type Parameter Types Return Type
nb_add binaryfunc PyObject * PyObject * PyObject *
nb_subtract binaryfunc PyObject * PyObject * PyObject *
nb_multiply binaryfunc PyObject * PyObject * PyObject *
nb_remainder binaryfunc PyObject * PyObject * PyObject *
nb_divmod binaryfunc PyObject * PyObject * PyObject *
nb_power ternaryfunc PyObject * PyObject * PyObject * PyObject *
nb_negative unaryfunc PyObject * PyObject *
nb_positive unaryfunc PyObject * PyObject *
nb_absolute unaryfunc PyObject * PyObject *
nb_bool inquiry PyObject * int
nb_invert unaryfunc PyObject * PyObject *
nb_lshift binaryfunc PyObject * PyObject * PyObject *
nb_rshift binaryfunc PyObject * PyObject * PyObject *
nb_and binaryfunc PyObject * PyObject * PyObject *
nb_xor binaryfunc PyObject * PyObject * PyObject *
nb_or binaryfunc PyObject * PyObject * PyObject *
nb_int unaryfunc PyObject * PyObject *
nb_reserved void *  
nb_float unaryfunc PyObject * PyObject *
nb_inplace_add binaryfunc PyObject * PyObject * PyObject *
nb_inplace_subtract binaryfunc PyObject * PyObject * PyObject *
nb_inplace_multiply binaryfunc PyObject * PyObject * PyObject *
nb_inplace_remainder binaryfunc PyObject * PyObject * PyObject *
nb_inplace_power ternaryfunc PyObject * PyObject * PyObject * PyObject *
nb_inplace_lshift binaryfunc PyObject * PyObject * PyObject *
nb_inplace_rshift binaryfunc PyObject * PyObject * PyObject *
nb_inplace_and binaryfunc PyObject * PyObject * PyObject *
nb_inplace_xor binaryfunc PyObject * PyObject * PyObject *
nb_inplace_or binaryfunc PyObject * PyObject * PyObject *
nb_floor_divide binaryfunc PyObject * PyObject * PyObject *
nb_true_divide binaryfunc PyObject * PyObject * PyObject *
nb_inplace_floor_divide | binaryfunc

PyObject * PyObject * PyObject *
nb_inplace_true_divide | binaryfunc

PyObject * PyObject * PyObject *
nb_index unaryfunc PyObject * PyObject *
PySequenceMethods Slot Type Parameter Types Return Type
sq_length lenfunc PyObject * Py_ssize_t
sq_concat binaryfunc PyObject * PyObject * PyObject *
sq_repeat ssizeargfunc PyObject * Py_ssize_t PyObject *
sq_item ssizeargfunc PyObject * Py_ssize_t PyObject *
sq_ass_item ssizeobjargproc PyObject * Py_ssize_t int
sq_contains objobjproc PyObject * PyObject * int
sq_inplace_concat binaryfunc PyObject * PyObject * PyObject *
sq_inplace_repeat ssizeargfunc PyObject * Py_ssize_t PyObject *
PyMappingMethods Slot Type Parameter Types Return Type
mp_length lenfunc PyObject * Py_ssize_t
mp_subscript binaryfunc PyObject * PyObject * PyObject *
mp_ass_subscript objobjargproc PyObject * PyObject * PyObject * int
PyBufferProcs Slot Type Parameter Types Return Type
bf_get_buffer getbufferproc PyObject * PyBuffer * int int
bf_release_buffer releasebufferproc PyObject * PyBuffer * void

PyTypeObject and Special Methods

Python’s flavor of operator overloading is achieved through “special methods”, a.k.a dunder methods, a.k.a magic methods [1]. They provide a simple and straightforward mechanism without getting in the way when you don’t need them. Likely you’re already familiar with a few of them: __init__(), __new__(), __str__(), and __repr__().

The CPython C-API, particularly PyTypeObject [2], provides a likewise (relatively) straightforward mechanism. Here we are exploring how the special methods relate to the Python types defined in C.

PyType_Ready() populates each type’s __dict__ with a wrappers around the various type slots. Not all of them are available on instances of the type.

One thing to note is that when __slots__ or __weakref__ are defined for a type, special handling happens for the time which impacts memory use. The creation/use of __dict__ is also impacted. It’s worth taking a little time to understand, though that’s outside the scope of this reference page.

Here’s a break-down of the slots that are exposed via Python attributes. Also, this table shows likewise exposed attributes that don’t actually correspond to type slots.

Legend: * The “Obj” column indicates if the method is available on instances. * The “Rdy” column indicates that the value is exposed by PyType_Ready(). * A slot name in parentheses means is is reserved or deprecated.

PyTypeObject Slot Special Method O b j R d y Notes
tp_name __name__     PyType_Type.tp_getset
tp_basicsize __basicsize__     PyType_Type.tp_members
tp_itemsize __itemsize__     PyType_Type.tp_members
tp_dealloc        
tp_print        
(tp_getattr) __getattribute__ __getattr__ X X  
(tp_setattr) __setattr__ __delattr__ X X  
(tp_reserved)        
tp_repr __repr__ X X  
tp_as_number (see below)
X  
tp_as_sequence (see below)
X  
tp_as_mapping (see below)
X  
tp_hash __hash__ X X  
tp_call __call__ X X  
tp_str __str__ X X  
tp_getattro __getattribute__ __getattr__ X X  
tp_setattro __setattr__ __delattr__ X X  
tp_as_buffer (see below)      
tp_flags __flags__     PyType_Type.tp_members
tp_doc __doc__ X   PyType_Type.tp_getset
tp_traverse        
tp_clear        
tp_richcompare __eq__ __ne__ __lt__ __gt__ __le__ __ge__ X X  
tp_weaklistoffset __weakrefoffset__     PyType_Type.tp_members
tp_iter __iter__ X X  
tp_iternext __next__ X X  
tp_methods (__dict__)
X  
tp_members (__dict__)
X  
tp_getset (__dict__)
X  
tp_base __base__     PyType_Type.tp_members
tp_dict __dict__     PyType_Type.tp_getset
tp_descr_get __get__ X X  
tp_descr_set __set__ __delete__ X X  
tp_dictoffset __dictoffset__     PyType_Type.tp_members
tp_init __init__ X X  
tp_alloc        
tp_new __new__ X X  
tp_free        
tp_is_gc        
tp_bases __bases__     PyType_Type.tp_getset
tp_mro __mro__     PyType_Type.tp_members
tp_cache        
tp_subclasses __subclasses__     PyType_Type.tp_methods
tp_weaklist __weakref__ X   dynamic types or manual
tp_del __del__ X X  
  __qualname__     PyType_Type.tp_getset
  __module__     PyType_Type.tp_getset
  __abstractmethods__     PyType_Type.tp_getset
  mro     PyType_Type.tp_methods
  __prepare__     PyType_Type.tp_methods
  __instancecheck__     PyType_Type.tp_methods
  __subclasscheck__     PyType_Type.tp_methods
  __dir__     PyType_Type.tp_methods
  __sizeof__     PyType_Type.tp_methods
PyNumberMethods Slot Special Method Usage
nb_add __add__ __radd__  
nb_subtract __sub__ __rsub__  
nb_multiply __mul__ __rmul__  
nb_remainder __mod__ __rmod__  
nb_divmod __divmod__ __rdivmod__  
nb_power __pow__ __rpow__  
nb_negative __neg__  
nb_positive __pos__  
nb_absolute __abs__  
nb_bool __bool__  
nb_invert __invert__  
nb_lshift __lshift__ __rlshift__  
nb_rshift __rshift__ __rrshift__  
nb_and __and__ __rand__  
nb_xor __xor__ __rxor__  
nb_or __or__ __ror__  
nb_int __int__  
nb_reserved  
nb_float __float__  
nb_inplace_add __iadd__  
nb_inplace_subtract __isub__  
nb_inplace_multiply __imul__  
nb_inplace_remainder __imod__  
nb_inplace_power __ipow__  
nb_inplace_lshift __ilshift__  
nb_inplace_rshift __irshift__  
nb_inplace_and __iand__  
nb_inplace_xor __ixor__  
nb_inplace_or __ior__  
nb_floor_divide __floordiv__ __rfloordiv__  
nb_true_divide __truediv__ __rtruediv__  
nb_inplace_floor_divide __ifloordiv__  
nb_inplace_true_divide __itruediv__  
nb_index __index__  
PySequenceMethods Slot Special Method Notes
sq_length __len__  
sq_concat __add__  
sq_repeat __mul__ __rmul__  
sq_item __getitem__  
sq_ass_item __setitem__ __delitem__  
sq_contains __contains__  
sq_inplace_concat __iadd__  
sq_inplace_repeat __imul__  
PyMappingMethods Slot Special Method Notes
mp_length __len__  
mp_subscript __getitem__  
mp_ass_subscript __setitem__ __getitem__  
PyBufferProcs Slot Special Method Notes
bf_get_buffer  
bf_release_buffer  

How They Get Used by the Interpreter

The usage of tp_print falls back to str(obj).

PyTypeObject Slot Special Method Usage
tp_name __name__  
tp_basicsize __basicsize__  
tp_itemsize __itemsize__  
tp_dealloc    
tp_print    
(tp_getattr) __getattribute__ __getattr__  
(tp_setattr) __setattr__ __delattr__  
(tp_reserved)    
tp_repr __repr__  
tp_as_number (see below)  
tp_as_sequence (see below)  
tp_as_mapping (see below)  
tp_hash __hash__  
tp_call __call__  
tp_str __str__  
tp_getattro __getattribute__ __getattr__  
tp_setattro __setattr__ __delattr__  
tp_as_buffer (see below)  
tp_flags __flags__  
tp_doc __doc__  
tp_traverse    
tp_clear    
tp_richcompare __eq__ __ne__ __lt__ __gt__ __le__ __ge__  
tp_weaklistoffset __weakrefoffset__  
tp_iter __iter__  
tp_iternext __next__  
tp_methods (__dict__)  
tp_members (__dict__)  
tp_getset (__dict__)  
tp_base __base__  
tp_dict __dict__  
tp_descr_get __get__  
tp_descr_set __set__ __delete__  
tp_dictoffset __dictoffset__  
tp_init __init__  
tp_alloc    
tp_new __new__  
tp_free    
tp_is_gc    
tp_bases __bases__  
tp_mro __mro__  
tp_cache    
tp_subclasses __subclasses__  
tp_weaklist __weakref__  
tp_del __del__  
  __qualname__  
  __module__  
  __abstractmethods__  
  mro  
  __prepare__  
  __instancecheck__  
  __subclasscheck__  
  __dir__  
  __sizeof__  
PyNumberMethods Slot Special Method Usage
nb_add __add__ __radd__  
nb_subtract __sub__ __rsub__  
nb_multiply __mul__ __rmul__  
nb_remainder __mod__ __rmod__  
nb_divmod __divmod__ __rdivmod__  
nb_power __pow__ __rpow__  
nb_negative __neg__  
nb_positive __pos__  
nb_absolute __abs__  
nb_bool __bool__  
nb_invert __invert__  
nb_lshift __lshift__ __rlshift__  
nb_rshift __rshift__ __rrshift__  
nb_and __and__ __rand__  
nb_xor __xor__ __rxor__  
nb_or __or__ __ror__  
nb_int __int__  
nb_reserved  
nb_float __float__  
nb_inplace_add __iadd__  
nb_inplace_subtract __isub__  
nb_inplace_multiply __imul__  
nb_inplace_remainder __imod__  
nb_inplace_power __ipow__  
nb_inplace_lshift __ilshift__  
nb_inplace_rshift __irshift__  
nb_inplace_and __iand__  
nb_inplace_xor __ixor__  
nb_inplace_or __ior__  
nb_floor_divide __floordiv__ __rfloordiv__  
nb_true_divide __truediv__ __rtruediv__  
nb_inplace_floor_divide __ifloordiv__  
nb_inplace_true_divide __itruediv__  
nb_index __index__  
PySequenceMethods Slot Special Method Usage
sq_length __len__  
sq_concat __add__  
sq_repeat __mul__ __rmul__  
sq_item __getitem__  
sq_ass_item __setitem__ __delitem__  
sq_contains __contains__  
sq_inplace_concat __iadd__  
sq_inplace_repeat __imul__  
PyMappingMethods Slot Special Method Usage
mp_length __len__  
mp_subscript __getitem__  
mp_ass_subscript __setitem__ __getitem__  
PyBufferProcs Slot Special Method Usage
bf_get_buffer  
bf_release_buffer  

How They Get Used by Built-in Functions

PyTypeObject Slot Special Method Usage
tp_name __name__  
tp_basicsize __basicsize__  
tp_itemsize __itemsize__  
tp_dealloc    
tp_print    
(tp_getattr) __getattribute__ __getattr__  
(tp_setattr) __setattr__ __delattr__  
(tp_reserved)    
tp_repr __repr__  
tp_as_number (see below)  
tp_as_sequence (see below)  
tp_as_mapping (see below)  
tp_hash __hash__  
tp_call __call__  
tp_str __str__  
tp_getattro __getattribute__ __getattr__  
tp_setattro __setattr__ __delattr__  
tp_as_buffer (see below)  
tp_flags __flags__  
tp_doc __doc__  
tp_traverse    
tp_clear    
tp_richcompare __eq__ __ne__ __lt__ __gt__ __le__ __ge__  
tp_weaklistoffset __weakrefoffset__  
tp_iter __iter__  
tp_iternext __next__  
tp_methods (__dict__)  
tp_members (__dict__)  
tp_getset (__dict__)  
tp_base __base__  
tp_dict __dict__  
tp_descr_get __get__  
tp_descr_set __set__ __delete__  
tp_dictoffset __dictoffset__  
tp_init __init__  
tp_alloc    
tp_new __new__  
tp_free    
tp_is_gc    
tp_bases __bases__  
tp_mro __mro__  
tp_cache    
tp_subclasses __subclasses__  
tp_weaklist __weakref__  
tp_del __del__  
  __qualname__  
  __module__  
  __abstractmethods__  
  mro  
  __prepare__  
  __instancecheck__  
  __subclasscheck__  
  __dir__  
  __sizeof__  
PyNumberMethods Slot Special Method Usage
nb_add __add__ __radd__  
nb_subtract __sub__ __rsub__  
nb_multiply __mul__ __rmul__  
nb_remainder __mod__ __rmod__  
nb_divmod __divmod__ __rdivmod__  
nb_power __pow__ __rpow__  
nb_negative __neg__  
nb_positive __pos__  
nb_absolute __abs__  
nb_bool __bool__  
nb_invert __invert__  
nb_lshift __lshift__ __rlshift__  
nb_rshift __rshift__ __rrshift__  
nb_and __and__ __rand__  
nb_xor __xor__ __rxor__  
nb_or __or__ __ror__  
nb_int __int__  
nb_reserved  
nb_float __float__  
nb_inplace_add __iadd__  
nb_inplace_subtract __isub__  
nb_inplace_multiply __imul__  
nb_inplace_remainder __imod__  
nb_inplace_power __ipow__  
nb_inplace_lshift __ilshift__  
nb_inplace_rshift __irshift__  
nb_inplace_and __iand__  
nb_inplace_xor __ixor__  
nb_inplace_or __ior__  
nb_floor_divide __floordiv__ __rfloordiv__  
nb_true_divide __truediv__ __rtruediv__  
nb_inplace_floor_divide __ifloordiv__  
nb_inplace_true_divide __itruediv__  
nb_index __index__  
PySequenceMethods Slot Special Method Usage
sq_length __len__  
sq_concat __add__  
sq_repeat __mul__ __rmul__  
sq_item __getitem__  
sq_ass_item __setitem__ __delitem__  
sq_contains __contains__  
sq_inplace_concat __iadd__  
sq_inplace_repeat __imul__  
PyMappingMethods Slot Special Method Usage
mp_length __len__  
mp_subscript __getitem__  
mp_ass_subscript __setitem__ __getitem__  
PyBufferProcs Slot Special Method Usage
bf_get_buffer  
bf_release_buffer  

How They Get Used by the C-API

PyTypeObject Slot Special Method Usage
tp_name __name__  
tp_basicsize __basicsize__  
tp_itemsize __itemsize__  
tp_dealloc    
tp_print    
(tp_getattr) __getattribute__ __getattr__  
(tp_setattr) __setattr__ __delattr__  
(tp_reserved)    
tp_repr __repr__  
tp_as_number (see below)  
tp_as_sequence (see below)  
tp_as_mapping (see below)  
tp_hash __hash__  
tp_call __call__  
tp_str __str__  
tp_getattro __getattribute__ __getattr__  
tp_setattro __setattr__ __delattr__  
tp_as_buffer (see below)  
tp_flags __flags__  
tp_doc __doc__  
tp_traverse    
tp_clear    
tp_richcompare __eq__ __ne__ __lt__ __gt__ __le__ __ge__  
tp_weaklistoffset __weakrefoffset__  
tp_iter __iter__  
tp_iternext __next__  
tp_methods (__dict__)  
tp_members (__dict__)  
tp_getset (__dict__)  
tp_base __base__  
tp_dict __dict__  
tp_descr_get __get__  
tp_descr_set __set__ __delete__  
tp_dictoffset __dictoffset__  
tp_init __init__  
tp_alloc    
tp_new __new__  
tp_free    
tp_is_gc    
tp_bases __bases__  
tp_mro __mro__  
tp_cache    
tp_subclasses __subclasses__  
tp_weaklist __weakref__  
tp_del __del__  
  __qualname__  
  __module__  
  __abstractmethods__  
  mro  
  __prepare__  
  __instancecheck__  
  __subclasscheck__  
  __dir__  
  __sizeof__  
PyNumberMethods Slot Special Method Usage
nb_add __add__ __radd__  
nb_subtract __sub__ __rsub__  
nb_multiply __mul__ __rmul__  
nb_remainder __mod__ __rmod__  
nb_divmod __divmod__ __rdivmod__  
nb_power __pow__ __rpow__  
nb_negative __neg__  
nb_positive __pos__  
nb_absolute __abs__  
nb_bool __bool__  
nb_invert __invert__  
nb_lshift __lshift__ __rlshift__  
nb_rshift __rshift__ __rrshift__  
nb_and __and__ __rand__  
nb_xor __xor__ __rxor__  
nb_or __or__ __ror__  
nb_int __int__  
nb_reserved  
nb_float __float__  
nb_inplace_add __iadd__  
nb_inplace_subtract __isub__  
nb_inplace_multiply __imul__  
nb_inplace_remainder __imod__  
nb_inplace_power __ipow__  
nb_inplace_lshift __ilshift__  
nb_inplace_rshift __irshift__  
nb_inplace_and __iand__  
nb_inplace_xor __ixor__  
nb_inplace_or __ior__  
nb_floor_divide __floordiv__ __rfloordiv__  
nb_true_divide __truediv__ __rtruediv__  
nb_inplace_floor_divide __ifloordiv__  
nb_inplace_true_divide __itruediv__  
nb_index __index__  
PySequenceMethods Slot Special Method Usage
sq_length __len__  
sq_concat __add__  
sq_repeat __mul__ __rmul__  
sq_item __getitem__  
sq_ass_item __setitem__ __delitem__  
sq_contains __contains__  
sq_inplace_concat __iadd__  
sq_inplace_repeat __imul__  
PyMappingMethods Slot Special Method Usage
mp_length __len__  
mp_subscript __getitem__  
mp_ass_subscript __setitem__ __getitem__  
PyBufferProcs Slot Special Method Usage
bf_get_buffer  
bf_release_buffer  

Footnotes

[1]See http://docs.python.org/3.4/reference/datamodel.html#special-method-names.
[2](1, 2) See http://docs.python.org/3.4/c-api/typeobj.html.

To Do

XXX fill out the “How They Get Used” sections XXX explain heap types XXX explicitly outline what PyType_Ready() does