2.6. Supported Python features

Apart from the Language part below, which applies to both object mode and nopython mode, this page only lists the features supported in nopython mode.

Warning

Numba behavior differs from Python semantics in some situations. We strongly advise reviewing Deviations from Python Semantics to become familiar with these differences.

2.6.1. Language

2.6.1.1. Constructs

Numba strives to support as much of the Python language as possible, but some language features are not available inside Numba-compiled functions. The following Python language features are not currently supported:

  • Class definition
  • Exception handling (try .. except, try .. finally)
  • Context management (the with statement)
  • Some comprehensions (list comprehension is supported, but not dict, set or generator comprehensions)
  • Generator delegation (yield from)

The raise statement is supported in several forms:

Similarly, the assert statement is supported with or without an error message.

2.6.1.2. Functions

2.6.1.2.1. Function calls

Numba supports function calls using positional and named arguments, as well as arguments with default values and *args (note the argument for *args can only be a tuple, not a list). Explicit **kwargs are not supported.

Function calls to locally defined inner functions are supported as long as they can be fully inlined.

2.6.1.2.2. Functions as arguments

Functions can be passed as argument into another function. But, they cannot be returned. For example:

from numba import jit

@jit
def add1(x):
    return x + 1

@jit
def bar(fn, x):
    return fn(x)

@jit
def foo(x):
    return bar(add1, x)

# Passing add1 within numba compiled code.
print(foo(1))
# Passing add1 into bar from interpreted code
print(bar(add1, 1))

Note

Numba does not handle function objects as real objects. Once a function is assigned to a variable, the variable cannot be re-assigned to a different function.

2.6.1.2.3. Inner function and closure

Numba now supports inner functions as long as they are non-recursive and only called locally, but not passed as argument or returned as result. The use of closure variables (variables defined in outer scopes) within an inner function is also supported.

2.6.1.2.4. Recursive calls

Most recursive call patterns are supported. The only restriction is that the recursive callee must have a control-flow path that returns without recursing. Numba is able to type-infer recursive functions without specifying the function type signature (which is required in numba 0.28 and earlier). Recursive calls can even call into a different overload of the function.

2.6.1.3. Generators

Numba supports generator functions and is able to compile them in object mode and nopython mode. The returned generator can be used both from Numba-compiled code and from regular Python code.

Coroutine features of generators are not supported (i.e. the generator.send(), generator.throw(), generator.close() methods).

2.6.2. Built-in types

2.6.2.1. int, bool

Arithmetic operations as well as truth values are supported.

The following attributes and methods are supported:

  • .conjugate()
  • .real
  • .imag

2.6.2.2. float, complex

Arithmetic operations as well as truth values are supported.

The following attributes and methods are supported:

  • .conjugate()
  • .real
  • .imag

2.6.2.3. tuple

The following operations are supported:

  • tuple construction
  • tuple unpacking
  • comparison between tuples
  • iteration and indexing over homogeneous tuples
  • addition (concatenation) between tuples
  • slicing tuples with a constant slice
  • the index method on tuples

2.6.2.4. list

Creating and returning lists from JIT-compiled functions is supported, as well as all methods and operations. Lists must be strictly homogeneous: Numba will reject any list containing objects of different types, even if the types are compatible (for example, [1, 2.5] is rejected as it contains a int and a float).

For example, to create a list of arrays:

In [1]: from numba import njit

In [2]: import numpy as np

In [3]: @njit
  ...: def foo(x):
  ...:     lst = []
  ...:     for i in range(x):
  ...:         lst.append(np.arange(i))
  ...:     return lst
  ...:

In [4]: foo(4)
Out[4]: [array([], dtype=int64), array([0]), array([0, 1]), array([0, 1, 2])]

2.6.2.4.1. List Reflection

In nopython mode, Numba does not operate on Python objects. list are compiled into an internal representation. Any list arguments must be converted into this representation on the way in to nopython mode and their contained elements must be restored in the original Python objects via a process called reflection. Reflection is required to maintain the same semantics as found in regular Python code. However, the reflection process can be expensive for large lists and it is not supported for lists that contain reflected data types. Users cannot use list-of-list as an argument because of this limitation.

Note

When passing a list into a JIT-compiled function, any modifications made to the list will not be visible to the Python interpreter until the function returns. (A limitation of the reflection process.)

Warning

List sorting currently uses a quicksort algorithm, which has different performance characterics than the algorithm used by Python.

2.6.2.4.2. List comprehension

Numba supports list comprehension. For example:

In [1]: from numba import njit

In [2]: @njit
  ...: def foo(x):
  ...:     return [[i for i in range(n)] for n in range(x)]
  ...:

In [3]: foo(3)
Out[3]: [[], [0], [0, 1]]

Note

Prior to version 0.39.0, Numba did not support the creation of nested lists.

Numba also supports “array comprehension” that is a list comprehension followed immediately by a call to numpy.array(). The following is an example that produces a 2D Numpy array:

from numba import jit
import numpy as np

@jit(nopython=True)
def f(n):
  return np.array([ [ x * y for x in range(n) ] for y in range(n) ])

In this case, Numba is able to optimize the program to allocate and initialize the result array directly without allocating intermediate list objects. Therefore, the nesting of list comprehension here is not a problem since a multi-dimensional array is being created here instead of a nested list.

Additionally, Numba supports parallel array comphension when combined with the parallel option on CPUs.

2.6.2.5. set

All methods and operations on sets are supported in JIT-compiled functions.

Sets must be strictly homogeneous: Numba will reject any set containing objects of different types, even if the types are compatible (for example, {1, 2.5} is rejected as it contains a int and a float).

Note

When passing a set into a JIT-compiled function, any modifications made to the set will not be visible to the Python interpreter until the function returns.

2.6.2.6. None

The None value is supported for identity testing (when using an optional type).

2.6.2.7. bytes, bytearray, memoryview

The bytearray type and, on Python 3, the bytes type support indexing, iteration and retrieving the len().

The memoryview type supports indexing, slicing, iteration, retrieving the len(), and also the following attributes:

2.6.3. Built-in functions

The following built-in functions are supported:

2.6.4. Standard library modules

2.6.4.1. array

Limited support for the array.array type is provided through the buffer protocol. Indexing, iteration and taking the len() is supported. All type codes are supported except for "u".

2.6.4.3. collections

Named tuple classes, as returned by collections.namedtuple(), are supported in the same way regular tuples are supported. Attribute access and named parameters in the constructor are also supported.

Creating a named tuple class inside Numba code is not supported; the class must be created at the global level.

2.6.4.4. ctypes

Numba is able to call ctypes-declared functions with the following argument and return types:

2.6.4.5. enum

Both enum.Enum and enum.IntEnum subclasses are supported.

2.6.4.8. functools

The functools.reduce() function is supported but the initializer argument is required.

2.6.4.9. random

Numba supports top-level functions from the random module, but does not allow you to create individual Random instances. A Mersenne-Twister generator is used, with a dedicated internal state. It is initialized at startup with entropy drawn from the operating system.

Note

Calling random.seed() from non-Numba code (or from object mode code) will seed the Python random generator, not the Numba random generator.

Note

Since version 0.28.0, the generator is thread-safe and fork-safe. Each thread and each process will produce independent streams of random numbers.

See also

Numba also supports most additional distributions from the Numpy random module.

2.6.5. Third-party modules

2.6.5.1. cffi

Similarly to ctypes, Numba is able to call into cffi-declared external functions, using the following C types and any derived pointer types:

  • char
  • short
  • int
  • long
  • long long
  • unsigned char
  • unsigned short
  • unsigned int
  • unsigned long
  • unsigned long long
  • int8_t
  • uint8_t
  • int16_t
  • uint16_t
  • int32_t
  • uint32_t
  • int64_t
  • uint64_t
  • float
  • double
  • ssize_t
  • size_t
  • void

The from_buffer() method of cffi.FFI and CompiledFFI objects is supported for passing Numpy arrays and other buffer-like objects. Only contiguous arguments are accepted. The argument to from_buffer() is converted to a raw pointer of the appropriate C type (for example a double * for a float64 array).

Additional type mappings for the conversion from a buffer to the appropriate C type may be registered with Numba. This may include struct types, though it is only permitted to call functions that accept pointers to structs - passing a struct by value is unsupported. For registering a mapping, use:

numba.cffi_support.register_type(cffi_type, numba_type)

Out-of-line cffi modules must be registered with Numba prior to the use of any of their functions from within Numba-compiled functions:

numba.cffi_support.register_module(mod)

Register the cffi out-of-line module mod with Numba.

Inline cffi modules require no registration.