In python you can define multiple functions that call each other in any order, and at runtime the functions will be called on. The order that these functions are defined in a script doesn't matter, once they exist. For example, the below is valid and will work
import numpy as np
def func1(arr):
out = np.empty_like(arr)
for i in range(arr.shape[0]):
out[i] = func2(arr[i]) # calling func2 here which is defined below
return out
def func2(a):
out = a + 1
return out
func1
can call on func2
even though func2
is defined after func1
.
However, if I decorate these functions with numba, I get an error
import numpy as np
import numba as nb
@nb.jit("f8[:](f8[:])", nopython=True)
def func1(arr):
out = np.empty_like(arr)
for i in range(arr.shape[0]):
out[i] = func2(arr[i])
return out
@nb.jit("f8(f8)", nopython=True)
def func2(a):
out = a + 1
return out
>>> TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Untyped global name 'func2': cannot determine Numba type of <class
'numba.ir.UndefinedType'>
So numba doesn't know what func2
is when compiling func1
using JIT. Simply switching the order of these functions works though, so that func2
comes before func1
@nb.jit("f8(f8)", nopython=True)
def func2(a):
out = a + 1
return out
@nb.jit("f8[:](f8[:])", nopython=True)
def func1(arr):
out = np.empty_like(arr)
for i in range(arr.shape[0]):
out[i] = func2(arr[i])
return out
Why is this? I have a feeling the pure python mode works because python is dynamically typed and not compiled, whereas numba, using JIT, by definition does compile the functions (and maybe therefore needs perfect knowledge of everything that happens within every function?). But I don't understand why numba doesn't search within the scope for all functions if it comes across a function it hasn't seen.