递归控制
These two functions provide a way to perform safe recursive calls at the C level, both in the core and in extension modules. They are needed if the recursive code does not necessarily invoke Python code (which tracks its recursion depth automatically). They are also not needed for tp_call implementations because the call protocol takes care of recursion handling.
int Py_EnterRecursiveCall
(const char *where)
Marks a point where a recursive C-level call is about to be performed.
If USE_STACKCHECK
is defined, this function checks if the OS stack overflowed using PyOS_CheckStack()
. In this is the case, it sets a MemoryError
and returns a nonzero value.
The function then checks if the recursion limit is reached. If this is the case, a RecursionError
is set and a nonzero value is returned. Otherwise, zero is returned.
where should be a UTF-8 encoded string such as " in instance check"
to be concatenated to the RecursionError
message caused by the recursion depth limit.
在 3.9 版更改: This function is now also available in the limited API.
void Py_LeaveRecursiveCall
(void)
Ends a Py_EnterRecursiveCall()
. Must be called once for each successful invocation of Py_EnterRecursiveCall()
.
在 3.9 版更改: This function is now also available in the limited API.
Properly implementing tp_repr
for container types requires special recursion handling. In addition to protecting the stack, tp_repr
also needs to track objects to prevent cycles. The following two functions facilitate this functionality. Effectively, these are the C equivalent to reprlib.recursive_repr()
.
int Py_ReprEnter
(PyObject *object)
Called at the beginning of the tp_repr
implementation to detect cycles.
If the object has already been processed, the function returns a positive integer. In that case the tp_repr
implementation should return a string object indicating a cycle. As examples, dict
objects return {...}
and list
objects return [...]
.
The function will return a negative integer if the recursion limit is reached. In that case the tp_repr
implementation should typically return NULL
.
Otherwise, the function returns zero and the tp_repr
implementation can continue normally.
void Py_ReprLeave
(PyObject *object)
Ends a Py_ReprEnter()
. Must be called once for each invocation of Py_ReprEnter()
that returns zero.