When learning numba, the concept of 'ufunc' is mentioned frequently.
Ufunc means Universal Functions, it apply certain computation on every single elements inside a numpy array.
@vectorize, as a decorator, basically converts the decorated function to a ufunc. I understand it as a much simpler way of .apply() or map() with a for loop iterating every single elements inside an array.
This is useful also because creating a ufunc requires coding in C, which could be hard and not so straight forward.
@guvectorize, on the other hand, is slightly different. This decorator won't return the underlying function's return, but return the last argument in the function. For example, in the offical file:
@guvectorize([(int64[:], int64, int64[:])], '(n),()->(n)')
def g(x, y, res):
for i in range(x.shape[0]):
res[i] = x[i] + y
As shown above, 'res' is the supposed return value, and it is more argument in the function 'g()'.
Like @jit, @vectorize and @guvectorize both support parameter (nopython=True) to avoid falling back to object mode.