How numpy.add get transformed into numpy.ufunc

  c++, numpy, python

I am trying to understand the implementation of numpy by debugging its source code.

I run the python code import numpy; numpy.add(1, 1) then use GDB to backtrace from its C implementation function LONG_add_avx2.

To my surprise, I don’t see the numpy.add appeared in the backtrace call stack. Instead, python is calling numpy.ufunc , not numpy.add!

Here is the stack trace.

LONG_add_avx2 loops.c.src:637
generic_wrapped_legacy_loop legacy_array_method.c:87
try_trivial_single_output_loop ufunc_object.c:1324
PyUFunc_GenericFunctionInternal ufunc_object.c:2623
ufunc_generic_fastcall ufunc_object.c:4878
_PyObject_Vectorcall abstract.h:127
**call_function ceval.c:4963**  # Here, the value of func->ob_type->tp_name is numpy.ufunc, not numpy.add !!!
_PyEval_EvalFrameDefault ceval.c:3469
PyEval_EvalFrameEx ceval.c:741
_PyEval_EvalCodeWithName ceval.c:4298
PyEval_EvalCodeEx ceval.c:4327
PyEval_EvalCode ceval.c:718
run_eval_code_obj pythonrun.c:1125
run_mod pythonrun.c:1147
PyRun_FileExFlags pythonrun.c:1063
PyRun_SimpleFileExFlags pythonrun.c:428
PyRun_AnyFileExFlags pythonrun.c:86
pymain_run_file main.c:381
pymain_run_python main.c:606
Py_RunMain main.c:685
pymain_main main.c:715
Py_BytesMain main.c:739
__libc_start_main 0x00007fc90eb970b3
_start 0x0000557140f9ad7e

I wonder how numpy.add magically get transformed into numpy.ufunc.
Pointing out relevant source code from numpy would be more appreciated.

Source: Python Questions