:const:`Py_TPFLAGS_HAVE_VERSION_TAG`.
- This bit is set when the :attr:`tp_finalize` slot is present in the
+ .. data:: Py_TPFLAGS_HAVE_FINALIZE
+
++ This bit is set when the :c:member:`~PyTypeObject.tp_finalize` slot is present in the
+ type structure.
+
+ .. versionadded:: 3.4
+
+
.. c:member:: char* PyTypeObject.tp_doc
An optional pointer to a NUL-terminated C string giving the docstring for this
This field is not inherited; it is calculated fresh by :c:func:`PyType_Ready`.
- If :attr:`tp_finalize` is set, the interpreter calls it once when
+.. c:member:: destructor PyTypeObject.tp_finalize
+
+ An optional pointer to an instance finalization function. Its signature is
+ :c:type:`destructor`::
+
+ void tp_finalize(PyObject *)
+
- :attr:`tp_finalize` should not mutate the current exception status;
++ If :c:member:`~PyTypeObject.tp_finalize` is set, the interpreter calls it once when
+ finalizing an instance. It is called either from the garbage
+ collector (if the instance is part of an isolated reference cycle) or
+ just before the object is deallocated. Either way, it is guaranteed
+ to be called before attempting to break reference cycles, ensuring
+ that it finds the object in a sane state.
+
++ :c:member:`~PyTypeObject.tp_finalize` should not mutate the current exception status;
+ therefore, a recommended way to write a non-trivial finalizer is::
+
+ static void
+ local_finalize(PyObject *self)
+ {
+ PyObject *error_type, *error_value, *error_traceback;
+
+ /* Save the current exception, if any. */
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
+ /* ... */
+
+ /* Restore the saved exception. */
+ PyErr_Restore(error_type, error_value, error_traceback);
+ }
+
+ For this field to be taken into account (even through inheritance),
+ you must also set the :const:`Py_TPFLAGS_HAVE_FINALIZE` flags bit.
+
+ This field is inherited by subtypes.
+
+ .. versionadded:: 3.4
+
+ .. seealso:: "Safe object finalization" (:pep:`442`)
+
+
.. c:member:: PyObject* PyTypeObject.tp_cache
Unused. Not inherited. Internal use only.
Py_TPFLAGS_DEFAULT, /* tp_flags */
All types should include this constant in their flags. It enables all of the
-members defined by the current version of Python.
+members defined until at least Python 3.3. If you need further members,
+you will need to OR the corresponding flags.
- We provide a doc string for the type in :attr:`tp_doc`. ::
+ We provide a doc string for the type in :c:member:`~PyTypeObject.tp_doc`. ::
"Noddy objects", /* tp_doc */
Py_TYPE(obj)->tp_free((PyObject*)self);
}
- First, if your type supports garbage collection (using :attr:`tp_traverse`
- and/or :attr:`tp_clear`), some of the object's members can have been
- cleared or finalized by the time :attr:`tp_dealloc` is called. Second, in
- :attr:`tp_dealloc`, your object is in an unstable state: its reference
+.. note::
+ There are limitations to what you can safely do in a deallocator function.
- example above) might end up calling :attr:`tp_dealloc` again, causing a
++ First, if your type supports garbage collection (using :c:member:`~PyTypeObject.tp_traverse`
++ and/or :c:member:`~PyTypeObject.tp_clear`), some of the object's members can have been
++ cleared or finalized by the time :c:member:`~PyTypeObject.tp_dealloc` is called. Second, in
++ :c:member:`~PyTypeObject.tp_dealloc`, your object is in an unstable state: its reference
+ count is equal to zero. Any call to a non-trivial object or API (as in the
- finalization code in :attr:`tp_dealloc`, and instead use the new
++ example above) might end up calling :c:member:`~PyTypeObject.tp_dealloc` again, causing a
+ double free and a crash.
+
+ Starting with Python 3.4, it is recommended not to put any complex
++ finalization code in :c:member:`~PyTypeObject.tp_dealloc`, and instead use the new
+ :c:member:`~PyTypeObject.tp_finalize` type method.
+
+ .. seealso::
+ :pep:`442` explains the new finalization scheme.
.. index::
single: string; object representation