Python Slots Performance
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. Similarly, Even Attack Wave also a periodic +6 bonus to Attack. However, this buff can be bestowed by a teammate instead, freeing up Python’s C slot skill for whatever his team may require. If Python is deployed exclusively alongside Cavalry heroes, Hone Cavalry is a great choice for a cheap but effective skill. I'm a Software Engineer located in Russia. My current technical interests are Machine learning, NLP, web security, Python, information extraction, network protocols, and software internals.
We’ve mentioned before how Oyster.com’s Python-based web servers cache huge amounts of static content in huge Python dicts (hash tables). Well, we recently saved over 2 GB in each of four 6 GB server processes with a single line of code — using __slots__
on our Image
class.
Here’s a screenshot of RAM usage before and after deploying this change on one of our servers:
Relative performance also often depends on your experience with the two languages. Use xrange instead of range. This section no longer applies if you're using Python 3, where range now provides an iterator over ranges of arbitrary size, and where xrange no longer exists. Python has two ways to get a range of numbers: range and xrange. Hello Python Forum, as a learning experience I created a very basic 'Slot' machine. It's far from perfect and could definitely use many upgrades, more winning options, pay tables, etc. As for this project I was mostly focusing on functionality, and I may continue working on it from time to time to make it better (more interesting to play).
We allocate about a million instances of a class like the following:
By default Python uses a dict to store an object’s instance attributes. Which is usually fine, and it allows fully dynamic things like setting arbitrary new attributes at runtime.
However, for small classes that have a few fixed attributes known at “compile time”, the dict is a waste of RAM, and this makes a real difference when you’re creating a million of them. You can tell Python not to use a dict, and only allocate space for a fixed set of attributes, by settings __slots__
on the class to a fixed list of attribute names:
Note that you can also use collections.namedtuple, which allows attribute access, but only takes the space of a tuple, so it’s similar to using __slots__
on a class. However, to me it always feels weird to inherit from a namedtuple class. Also, if you want a custom initializer you have to override __new__
rather than __init__
.
Warning: Don’t prematurely optimize and use this everywhere! It’s not great for code maintenance, and it really only saves you when you have thousands of instances.
CPython includes a powerful C-API by which you can heavily customizePython. This includes creating custom types. Though you can create newtypes directly in Python now, this wasn’t always the case. Python has astrong heritage of tapping into C to produce new types. One consequenceis that creating new Python types in C affords you more functionalitythan you’ll find in pure Python.
In this reference page we’ll be looking at the details surroundingPyTypeObject, 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 ofinterfaces for efficiently interacting with Python objects in C. Thosefunctions 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 theirrespective types to get improved efficiency and functionality. However,this comes at the cost of ignoring implementations in subtypes. The dictconcrete API is a prime example of this, as it make direct calls tostatic methods in the implementation, skipping a lookup of the relevantimplementation on the type. This situation likely won’t change anytimesoon due to the challenge of accommodating subtypes without damagingperformance or functionality.
PyTypeObject, the Base Type Struct¶
The PyTypeObject, exposed in Python as type, is the cornerstone of thetype system implementation in CPython.
Note: A “dynamic” type is one created through the class statement inPython (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 aPyTypeObject struct with the values you care about. We call each ofthose 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 thetype 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]. Itdoes not include the slots provided by PyObject_VAR_HEAD, etc., northose 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 | Req | Rdy | Mem | Description |
---|---|---|---|---|
tp_name | X | The class’s name, possiblyfully 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 forwriting 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 orremove 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 structfor 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 forinstance 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_GCisn’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 whendefining a type, except for tp_flags.
Note: various flag bits in tp_flags may cause certain slots to beignored.
Note: tp_print is effectively deprecated, so don’t use it.
Note: PyType_Ready() will build the new type with consideration forthe various inherited slots. Thus, it effectively makes use of thoseslots.
Inheritance¶
Python types written in C still enjoy inheritance, but it’s a littledifferent than in Python. For one thing, only single-inheritance issupported at the C level. For another, at the C level PyTypeReadyfacilitates a form of inheritance-by-copy. This is where inheritedvalues are actually copied into the subclass.
Attribute lookup works the same either way, however. This means thatvalues which PyType_Ready did not copy into the subclass are stillavailable as long as they are exposed vi the base class’s __dict__.
Here’s a look at how inheritance-by-copy works for the variousPyTypeObject slots:
Legend:* The “Inh” column is more complicated:
The “Grp” column indicates inheritance dependencies:
PyTypeObject Slot | Inh | Grp | 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 byinheritance or by explicit setting (PyType_Ready). Here is a breakdownof what slots have defaults, where they come from, and what those valuesare:
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_DEFAULTPy_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_GenericAllocPyType_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. Eachof these function “types” (e.g. reprfunc) is actually a macro for aparticular function pointer cast.
Consequently, each function you set in your type definition must be castusing that macro:
For each of those slots the following table indicates the function’sparameters and return type. For non-function slots, just the slot’stype 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 themain 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 muchmemory.
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 * |
| PyObject *PyObject * | PyObject * | |
| 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 “specialmethods”, a.k.a dunder methods, a.k.a magic methods [1].They provide a simple and straightforward mechanism without getting inthe way when you don’t need them. Likely you’re already familiar with afew of them: __init__(), __new__(), __str__(), and __repr__().
The CPython C-API, particularly PyTypeObject [2], providesa likewise (relatively) straightforward mechanism. Here we areexploring how the special methods relate to the Python types defined in C.
PyType_Ready() populates each type’s __dict__ with a wrappers aroundthe various type slots. Not all of them are available on instances ofthe type.
One thing to note is that when __slots__ or __weakref__ are defined fora type, special handling happens for the time which impacts memory use.The creation/use of __dict__ is also impacted. It’s worth taking alittle time to understand, though that’s outside the scope of thisreference 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 actuallycorrespond 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 | Obj | Rdy | 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__ |
Python Slots Performance Tool
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. |
Monty Python Slot Machine App
To Do¶
XXX fill out the “How They Get Used” sectionsXXX explain heap typesXXX explicitly outline what PyType_Ready() does