Extending and Embedding Python, Release 3.9.5 Chapter 2. Creating extensions without third party tools 30 (continues on next page) (continued from previous page) and install it in the tp_new member: The tp_new handler is responsible for creating (as opposed to initializing) objects of the type. It is exposed in Python as the$_{__new__()}$ method. It is not required to define a$_{tp_new}$ member, and indeed many extension types will simply reuse$_{PyType_GenericNew()}$as done in the first version of the$_{Custom}$type above. In this case, we use the$_{tp_new}$ handler to initialize the$_{first}$ and$_{last}$attributes to non-$_{NULL}$ default values. tp_new is passed the type being instantiated (not necessarily$_{CustomType}$, if a subclass is instantiated) and any arguments passed when the type was called, and is expected to return the instance created. tp_new handlers always accept positional and keyword arguments, but they often ignore the arguments, leaving the argument handling to initializer (a.k.a. tp_init in C or __init__ in Python) methods. Note: tp_new shouldn’t call tp_init explicitly, as the interpreter will do it itself. The tp_new implementation calls the tp_alloc slot to allocate memory: self=(CustomObject*) type->tp_alloc(type, 0); Since memory allocation may fail, we must check the$_{tp_alloc}$ result against$_{NULL}$ before proceeding. Note: We didn’t fill the$_{tp_alloc}$ slot ourselves. Rather$_{PyType_Ready()}$ fills it for us by inheriting it from our base class, which is$_{object}$by default. Most types use the default allocation strategy. Note: If you are creating a co-operative$_{tp_new}$ (one that calls a base type’s$_{tp_new}$ or$_{__new__()}$ ), you must not try to determine what method to call using method resolution order at runtime. Always statically determine what type you are going to call, and call its$_{tp_new}$ directly, or via$_{type->tp_base->tp_new}$ . If you do not do this, Python subclasses of your type that also inherit from other Python-defined classes may not work correctly. (Specifically, you may not be able to create instances of such subclasses without getting a$_{TypeError}$.) We also define an initialization function which accepts arguments to provide initial values for our instance: static int Custom_init(CustomObject *self, PyObject*args, PyObject*kwds) { static char *kwlist[] ={ "first","last","number",NULL }; PyObject *first =NULL ,*last=NULL ,*tmp; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi ", kwlist, &first,&last, &self->number)) return -1 ; if (first) { tmp =self->first; Py_INCREF(first); self->first =first; Py_XDECREF(tmp); } if (last) { tmp =self->last; .tp_new=Custom_new, } return (PyObject*) self; }