# 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.

## Language

### Constructs

Numba strives to support as much of the Python language as possible, but some language features are not available inside Numba-compiled functions. Below is a quick reference for the support level of Python constructs.

Supported constructs:

- conditional branch: `if .. elif .. else`

- loops: `while`, `for .. in`, `break`, `continue`

- basic generator: `yield`

- assertion: `assert`

Partially supported constructs:

- exceptions: `try .. except`, `raise`, `else` and `finally` (See details in this section)

- context manager: `with` (only support numba.objmode())

- list comprehension (see details in this section)

Unsupported constructs:

- async features: `async with`, `async for` and `async def`

- class definition: `class` (except for @jitclass)

- set, dict and generator comprehensions

- generator delegation: `yield from`

- Deletion with `del` statements

### Functions

#### 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.

#### 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.

#### 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.

#### 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.

### 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).

### Exception handling

#### `raise` statement

The `raise` statement is only supported in the following forms:

- `raise SomeException`

- `raise SomeException(<arguments>)`

It is currently unsupported to re-raise an exception created in compiled code.

#### `try .. except`

The `try .. except` construct is partially supported. The following forms of are supported:

- the bare except that captures all exceptions:

      try:
          ...
      except:
          ...

- using exactly the `Exception` class in the `except` clause:

      try:
        ...
      except Exception:
        ...

  This will match any exception that is a subclass of `Exception` as expected. Currently, instances of `Exception` and it’s subclasses are the only kind of exception that can be raised in compiled code.

Warning

Numba currently masks signals like `KeyboardInterrupt` and `SystemExit`. These signaling exceptions are ignored during the execution of Numba compiled code. The Python interpreter will handle them as soon as the control is returned to it.

Currently, exception objects are not materialized inside compiled functions. As a result, it is not possible to store an exception object into a user variable or to re-raise an exception. With this limitation, the only realistic use-case would look like:

    try:
       do_work()
    except Exception:
       handle_error_case()
       return error_code

#### `try .. except .. else .. finally`

The `else` block and the `finally` block of a `try .. except` are supported:

>     >>> @jit(nopython=True)
>     ... def foo():
>     ...     try:
>     ...         print('main block')
>     ...     except Exception:
>     ...         print('handler block')
>     ...     else:
>     ...         print('else block')
>     ...     finally:
>     ...         print('final block')
>     ...
>     >>> foo()
>     main block
>     else block
>     final block

The `try .. finally` construct without the `except` clause is also supported.

## Built-in types

### int, bool

Arithmetic operations as well as truth values are supported.

The following attributes and methods are supported:

- `.conjugate()`

- `.real`

- `.imag`

### float, complex

Arithmetic operations as well as truth values are supported.

The following attributes and methods are supported:

- `.conjugate()`

- `.real`

- `.imag`

### str

Numba supports (Unicode) strings in Python 3. Strings can be passed into nopython mode as arguments, as well as constructed and returned from nopython mode. As in Python, slices (even of length 1) return a new, reference counted string. Optimized code paths for efficiently accessing single characters may be introduced in the future.

The in-memory representation is the same as was introduced in Python 3.4, with each string having a tag to indicate whether the string is using a 1, 2, or 4 byte character width in memory. When strings of different encodings are combined (as in concatenation), the resulting string automatically uses the larger character width of the two input strings. String slices also use the same character width as the original string, even if the slice could be represented with a narrower character width. (These details are invisible to the user, of course.)

The following constructors, functions, attributes and methods are currently supported:

- `str(int)`

- `len()`

- `+` (concatenation of strings)

- `*` (repetition of strings)

- `in`, `.contains()`

- `==`, `<`, `<=`, `>`, `>=` (comparison)

- `.capitalize()`

- `.casefold()`

- `.center()`

- `.count()`

- `.endswith()`

- `.endswith()`

- `.expandtabs()`

- `.find()`

- `.index()`

- `.isalnum()`

- `.isalpha()`

- `.isdecimal()`

- `.isdigit()`

- `.isidentifier()`

- `.islower()`

- `.isnumeric()`

- `.isprintable()`

- `.isspace()`

- `.istitle()`

- `.isupper()`

- `.join()`

- `.ljust()`

- `.lower()`

- `.lstrip()`

- `.partition()`

- `.replace()`

- `.rfind()`

- `.rindex()`

- `.rjust()`

- `.rpartition()`

- `.rsplit()`

- `.rstrip()`

- `.split()`

- `.splitlines()`

- `.startswith()`

- `.strip()`

- `.swapcase()`

- `.title()`

- `.upper()`

- `.zfill()`

Regular string literals (e.g. `"ABC"`) as well as f-strings without format specs (e.g. `"ABC_{a+1}"`) that only use string and integer variables (types with `str()` overload) are supported in nopython mode.

Additional operations as well as support for Python 2 strings / Python 3 bytes will be added in a future version of Numba. Python 2 Unicode objects will likely never be supported.

Warning

The performance of some operations is known to be slower than the CPython implementation. These include substring search (`in`, `.contains()` and `find()`) and string creation (like `.split()`). Improving the string performance is an ongoing task, but the speed of CPython is unlikely to be surpassed for basic string operation in isolation. Numba is most successfully used for larger algorithms that happen to involve strings, where basic string operations are not the bottleneck.

### tuple

Tuple support is categorised into two categories based on the contents of a tuple. The first category is homogeneous tuples, these are tuples where the type of all the values in the tuple are the same, the second is heterogeneous tuples, these are tuples where the types of the values are different.

Note

The `tuple()` constructor itself is NOT supported.

### homogeneous tuples

An example of a homogeneous tuple:

    homogeneous_tuple = (1, 2, 3, 4)

The following operations are supported on homogeneous tuples:

- Tuple construction.

- Tuple unpacking.

- Comparison between tuples.

- Iteration and indexing.

- Addition (concatenation) between tuples.

- Slicing tuples with a constant slice.

- The index method on tuples.

### heterogeneous tuples

An example of a heterogeneous tuple:

    heterogeneous_tuple = (1, 2j, 3.0, "a")

The following operations are supported on heterogeneous tuples:

- Comparison between tuples.

- Indexing using an index value that is a compile time constant e.g. `mytuple[7]`, where `7` is evidently a constant.

- Iteration over a tuple (requires experimental `literal_unroll()` feature, see below).

Warning

The following feature (`literal_unroll()`) is experimental and was added in version 0.47.

To permit iteration over a heterogeneous tuple the special function `numba.literal_unroll()` must be used. This function has no effect other than to act as a token to permit the use of this feature. Example use:

    from numba import njit, literal_unroll

    @njit
    def foo():
        heterogeneous_tuple = (1, 2j, 3.0, "a")
        for i in literal_unroll(heterogeneous_tuple):
            print(i)

Warning

The following restrictions apply to the use of `literal_unroll()`:

- `literal_unroll()` can only be used on tuples and constant lists of compile time constants, e.g. `[1, 2j, 3, "a"]` and the list not being mutated.

- The only supported use pattern for `literal_unroll()` is loop iteration.

- Only one `literal_unroll()` call is permitted per loop nest (i.e. nested heterogeneous tuple iteration loops are forbidden).

- The usual type inference/stability rules still apply.

A more involved use of `literal_unroll()` might be type specific dispatch, recall that string and integer literal values are considered their own type, for example:

    from numba import njit, types, literal_unroll
    from numba.extending import overload

    def dt(x):
        # dummy function to overload
        pass

    @overload(dt, inline='always')
    def ol_dt(li):
        if isinstance(li, types.StringLiteral):
            value = li.literal_value
            if value == "apple":
                def impl(li):
                    return 1
            elif value == "orange":
                def impl(li):
                    return 2
            elif value == "banana":
                def impl(li):
                    return 3
            return impl
        elif isinstance(li, types.IntegerLiteral):
            value = li.literal_value
            if value == 0xca11ab1e:
                def impl(li):
                    # capture the dispatcher literal value
                    return 0x5ca1ab1e + value
                return impl

    @njit
    def foo():
        acc = 0
        for t in literal_unroll(('apple', 'orange', 'banana', 3390155550)):
            acc += dt(t)
        return acc

    print(foo())

### list

Warning

As of version 0.45.x the internal implementation for the list datatype in Numba is changing. Until recently, only a single implementation of the list datatype was available, the so-called reflected-list (see below). However, it was scheduled for deprecation from version 0.44.0 onwards due to its limitations. As of version 0.45.0 a new implementation, the so-called typed-list (see below), is available as an experimental feature. For more information, please see: Deprecation Notices.

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])]

#### 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.

#### Initial Values

Warning

This is an experimental feature!

Lists that:

- Are constructed using the square braces syntax

- Have values of a literal type

will have their initial value stored in the `.initial_value` property on the type so as to permit inspection of these values at compile time. If required, to force value based dispatch the literally function will accept such a list.

Example:

from `test_ex_initial_value_list_compile_time_consts` of `numba/tests/doc_examples/test_literal_container_usage.py`

     1from numba import njit, literally
     2from numba.extending import overload
     3
     4# overload this function
     5def specialize(x):
     6    pass
     7
     8@overload(specialize)
     9def ol_specialize(x):
    10    iv = x.initial_value
    11    if iv is None:
    12        return lambda x: literally(x) # Force literal dispatch
    13    assert iv == [1, 2, 3] # INITIAL VALUE
    14    return lambda x: x
    15
    16@njit
    17def foo():
    18    l = [1, 2, 3]
    19    l[2] = 20 # no impact on .initial_value
    20    l.append(30) # no impact on .initial_value
    21    return specialize(l)
    22
    23result = foo()
    24print(result) # [1, 2, 20, 30] # NOT INITIAL VALUE!

#### Typed List

Note

`numba.typed.List` is an experimental feature, if you encounter any bugs in functionality or suffer from unexpectedly bad performance, please report this, ideally by opening an issue on the Numba issue tracker.

As of version 0.45.0 a new implementation of the list data type is available, the so-called typed-list. This is compiled library backed, type-homogeneous list data type that is an improvement over the reflected-list mentioned above. Additionally, lists can now be arbitrarily nested. Since the implementation is considered experimental, you will need to import it explicitly from the numba.typed module:

    In [1]: from numba.typed import List

    In [2]: from numba import njit

    In [3]: @njit
    ...: def foo(l):
    ...:     l.append(23)
    ...:     return l
    ...:

    In [4]: mylist = List()

    In [5]: mylist.append(1)

    In [6]: foo(mylist)
    Out[6]: ListType[int64]([1, 23])

Note

As the typed-list stabilizes it will fully replace the reflected-list and the constructors [] and list() will create a typed-list instead of a reflected one.

Here’s an example using `List()` to create `numba.typed.List` inside a jit-compiled function and letting the compiler infer the item type:

from `ex_inferred_list_jit` of `numba/tests/doc_examples/test_typed_list_usage.py`

     1from numba import njit
     2from numba.typed import List
     3
     4@njit
     5def foo():
     6    # Instantiate a typed-list
     7    l = List()
     8    # Append a value to it, this will set the type to int32/int64
     9    # (depending on platform)
    10    l.append(42)
    11    # The usual list operations, getitem, pop and length are
    12    # supported
    13    print(l[0])   # 42
    14    l[0] = 23
    15    print(l[0])   # 23
    16    print(len(l)) # 1
    17    l.pop()
    18    print(len(l)) # 0
    19    return l
    20
    21foo()
    22

Here’s an example of using `List()` to create a `numba.typed.List` outside of a jit-compiled function and then using it as an argument to a jit-compiled function:

from `ex_inferred_list` of `numba/tests/doc_examples/test_typed_list_usage.py`

     1from numba import njit
     2from numba.typed import List
     3
     4@njit
     5def foo(mylist):
     6    for i in range(10, 20):
     7        mylist.append(i)
     8    return mylist
     9
    10# Instantiate a typed-list, outside of a jit context
    11l = List()
    12# Append a value to it, this will set the type to int32/int64
    13# (depending on platform)
    14l.append(42)
    15# The usual list operations, getitem, pop and length are supported
    16print(l[0])   # 42
    17l[0] = 23
    18print(l[0])   # 23
    19print(len(l)) # 1
    20l.pop()
    21print(len(l)) # 0
    22
    23# And you can use the typed-list as an argument for a jit compiled
    24# function
    25l = foo(l)
    26print(len(l)) # 10
    27
    28# You can also directly construct a typed-list from an existing
    29# Python list
    30py_list = [2, 3, 5]
    31numba_list = List(py_list)
    32print(len(numba_list)) # 3
    33

Finally, here’s an example of using a nested List():

from `ex_nested_list` of `numba/tests/doc_examples/test_typed_list_usage.py`

     1from numba.typed import List
     2
     3# typed-lists can be nested in typed-lists
     4mylist = List()
     5for i in range(10):
     6    l = List()
     7    for i in range(10):
     8        l.append(i)
     9    mylist.append(l)
    10# mylist is now a list of 10 lists, each containing 10 integers
    11print(mylist)
    12

#### Literal List

Warning

This is an experimental feature!

Numba supports the use of literal lists containing any values, for example:

    l = ['a', 1, 2j, np.zeros(5,)]

the predominant use of these lists is for use as a configuration object. The lists appear as a `LiteralList` type which inherits from `Literal`, as a result the literal values of the list items are available at compile time. For example:

from `test_ex_literal_list` of `numba/tests/doc_examples/test_literal_container_usage.py`

     1from numba import njit
     2from numba.extending import overload
     3
     4# overload this function
     5def specialize(x):
     6    pass
     7
     8@overload(specialize)
     9def ol_specialize(x):
    10    l = x.literal_value
    11    const_expr = []
    12    for v in l:
    13        const_expr.append(str(v))
    14    const_strings = tuple(const_expr)
    15
    16    def impl(x):
    17        return const_strings
    18    return impl
    19
    20@njit
    21def foo():
    22    const_list = ['a', 10, 1j, ['another', 'list']]
    23    return specialize(const_list)
    24
    25result = foo()
    26print(result) # ('Literal[str](a)', 'Literal[int](10)', 'complex128', 'list(unicode_type)') # noqa E501

Important things to note about these kinds of lists:

1. They are immutable, use of mutating methods e.g. `.pop()` will result in compilation failure. Read-only static access and read only methods are supported e.g. `len()`.

2. Dynamic access of items is not possible, e.g. `some_list[x]`, for a value `x` which is not a compile time constant. This is because it’s impossible to statically determine the type of the item being accessed.

3. Inside the compiler, these lists are actually just tuples with some extra things added to make them look like they are lists.

4. They cannot be returned to the interpreter from a compiled function.

#### 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 comprehension when combined with the parallel option on CPUs.

### 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`). The use of reference counted types, e.g. strings, in sets is unsupported.

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.

### Typed Dict

Warning

`numba.typed.Dict` is an experimental feature. The API may change in the future releases.

Note

`dict()` was not supported in versions prior to 0.44. Currently, calling `dict()` translates to calling `numba.typed.Dict()`.

Numba supports the use of `dict()`. Such use is semantically equivalent to `{}` and `numba.typed.Dict()`. It will create an instance of `numba.typed.Dict` where the key-value types will be later inferred by usage. Numba also supports, explicitly, the `dict(iterable)` constructor.

Numba does not fully support the Python `dict` because it is an untyped container that can have any Python types as members. To generate efficient machine code, Numba needs the keys and the values of the dictionary to have fixed types, declared in advance. To achieve this, Numba has a typed dictionary, `numba.typed.Dict`, for which the type-inference mechanism must be able to infer the key-value types by use, or the user must explicitly declare the key-value type using the `Dict.empty()` constructor method. This typed dictionary has the same API as the Python `dict`, it implements the `collections.MutableMapping` interface and is usable in both interpreted Python code and JIT-compiled Numba functions. Because the typed dictionary stores keys and values in Numba’s native, unboxed data layout, passing a Numba dictionary into nopython mode has very low overhead. However, this means that using a typed dictionary from the Python interpreter is slower than a regular dictionary because Numba has to box and unbox key and value objects when getting or setting items.

An important difference of the typed dictionary in comparison to Python’s `dict` is that implicit casting occurs when a key or value is stored. As a result the setitem operation may fail should the type-casting fail.

It should be noted that the Numba typed dictionary is implemented using the same algorithm as the CPython 3.7 dictionary. As a consequence, the typed dictionary is ordered and has the same collision resolution as the CPython implementation.

Further to the above in relation to type specification, there are limitations placed on the types that can be used as keys and/or values in the typed dictionary, most notably the Numba `Set` and `List` types are currently unsupported. Acceptable key/value types include but are not limited to: unicode strings, arrays (value only), scalars, tuples. It is expected that these limitations will be relaxed as Numba continues to improve.

Here’s an example of using `dict()` and `{}` to create `numba.typed.Dict` instances and letting the compiler infer the key-value types:

from `test_ex_inferred_dict_njit` of `numba/tests/doc_examples/test_typed_dict_usage.py`

     1from numba import njit
     2import numpy as np
     3
     4@njit
     5def foo():
     6    d = dict()
     7    k = {1: np.arange(1), 2: np.arange(2)}
     8    # The following tells the compiler what the key type and the
     9    # value
    10    # type are for `d`.
    11    d[3] = np.arange(3)
    12    d[5] = np.arange(5)
    13    return d, k
    14
    15d, k = foo()
    16print(d)    # {3: [0 1 2], 5: [0 1 2 3 4]}
    17print(k)    # {1: [0], 2: [0 1]}

Here’s an example of creating a `numba.typed.Dict` instance from interpreted code and using the dictionary in jit code:

from `test_ex_typed_dict_from_cpython` of `numba/tests/doc_examples/test_typed_dict_usage.py`

     1import numpy as np
     2from numba import njit
     3from numba.core import types
     4from numba.typed import Dict
     5
     6# The Dict.empty() constructs a typed dictionary.
     7# The key and value typed must be explicitly declared.
     8d = Dict.empty(
     9    key_type=types.unicode_type,
    10    value_type=types.float64[:],
    11)
    12
    13# The typed-dict can be used from the interpreter.
    14d['posx'] = np.asarray([1, 0.5, 2], dtype='f8')
    15d['posy'] = np.asarray([1.5, 3.5, 2], dtype='f8')
    16d['velx'] = np.asarray([0.5, 0, 0.7], dtype='f8')
    17d['vely'] = np.asarray([0.2, -0.2, 0.1], dtype='f8')
    18
    19# Here's a function that expects a typed-dict as the argument
    20@njit
    21def move(d):
    22    # inplace operations on the arrays
    23    d['posx'] += d['velx']
    24    d['posy'] += d['vely']
    25
    26print('posx: ', d['posx'])  # Out: posx:  [1.  0.5 2. ]
    27print('posy: ', d['posy'])  # Out: posy:  [1.5 3.5 2. ]
    28
    29# Call move(d) to inplace update the arrays in the typed-dict.
    30move(d)
    31
    32print('posx: ', d['posx'])  # Out: posx:  [1.5 0.5 2.7]
    33print('posy: ', d['posy'])  # Out: posy:  [1.7 3.3 2.1]

Here’s an example of creating a `numba.typed.Dict` instance from jit code and using the dictionary in interpreted code:

from `test_ex_typed_dict_njit` of `numba/tests/doc_examples/test_typed_dict_usage.py`

     1import numpy as np
     2from numba import njit
     3from numba.core import types
     4from numba.typed import Dict
     5
     6# Make array type.  Type-expression is not supported in jit
     7# functions.
     8float_array = types.float64[:]
     9
    10@njit
    11def foo():
    12    # Make dictionary
    13    d = Dict.empty(
    14        key_type=types.unicode_type,
    15        value_type=float_array,
    16    )
    17    # Fill the dictionary
    18    d["posx"] = np.arange(3).astype(np.float64)
    19    d["posy"] = np.arange(3, 6).astype(np.float64)
    20    return d
    21
    22d = foo()
    23# Print the dictionary
    24print(d)  # Out: {posx: [0. 1. 2.], posy: [3. 4. 5.]}

It should be noted that `numba.typed.Dict` is not thread-safe. Specifically, functions which modify a dictionary from multiple threads will potentially corrupt memory, causing a range of possible failures. However, the dictionary can be safely read from multiple threads as long as the contents of the dictionary do not change during the parallel access.

#### Dictionary comprehension

Numba supports dictionary comprehension under the assumption that a `numba.typed.Dict` instance can be created from the comprehension. For example:

    In [1]: from numba import njit

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

    In [3]: foo(3)
    Out[3]: DictType[int64,int64]<iv=None>({0: 0, 1: 1, 2: 4})

#### Initial Values

Warning

This is an experimental feature!

Typed dictionaries that:

- Are constructed using the curly braces syntax

- Have literal string keys

- Have values of a literal type

will have their initial value stored in the `.initial_value` property on the type so as to permit inspection of these values at compile time. If required, to force value based dispatch the literally function will accept a typed dictionary.

Example:

from `test_ex_initial_value_dict_compile_time_consts` of `numba/tests/doc_examples/test_literal_container_usage.py`

     1from numba import njit, literally
     2from numba.extending import overload
     3
     4# overload this function
     5def specialize(x):
     6    pass
     7
     8@overload(specialize)
     9def ol_specialize(x):
    10    iv = x.initial_value
    11    if iv is None:
    12        return lambda x: literally(x) # Force literal dispatch
    13    assert iv == {'a': 1, 'b': 2, 'c': 3} # INITIAL VALUE
    14    return lambda x: literally(x)
    15
    16@njit
    17def foo():
    18    d = {'a': 1, 'b': 2, 'c': 3}
    19    d['c'] = 20 # no impact on .initial_value
    20    d['d'] = 30 # no impact on .initial_value
    21    return specialize(d)
    22
    23result = foo()
    24print(result) # {a: 1, b: 2, c: 20, d: 30} # NOT INITIAL VALUE!

### Heterogeneous Literal String Key Dictionary

Warning

This is an experimental feature!

Numba supports the use of statically declared string key to any value dictionaries, for example:

    d = {'a': 1, 'b': 'data', 'c': 2j}

the predominant use of these dictionaries is to orchestrate advanced compilation dispatch or as a container for use as a configuration object. The dictionaries appear as a `LiteralStrKeyDict` type which inherits from `Literal`, as a result the literal values of the keys and the types of the items are available at compile time. For example:

from `test_ex_literal_dict_compile_time_consts` of `numba/tests/doc_examples/test_literal_container_usage.py`

     1import numpy as np
     2from numba import njit, types
     3from numba.extending import overload
     4
     5# overload this function
     6def specialize(x):
     7    pass
     8
     9@overload(specialize)
    10def ol_specialize(x):
    11    ld = x.literal_value
    12    const_expr = []
    13    for k, v in ld.items():
    14        if isinstance(v, types.Literal):
    15            lv = v.literal_value
    16            if lv == 'cat':
    17                const_expr.append("Meow!")
    18            elif lv == 'dog':
    19                const_expr.append("Woof!")
    20            elif isinstance(lv, int):
    21                const_expr.append(k.literal_value * lv)
    22        else: # it's an array
    23            const_expr.append("Array(dim={dim}".format(dim=v.ndim))
    24    const_strings = tuple(const_expr)
    25
    26    def impl(x):
    27        return const_strings
    28    return impl
    29
    30@njit
    31def foo():
    32    pets_ints_and_array = {'a': 1,
    33                           'b': 2,
    34                           'c': 'cat',
    35                           'd': 'dog',
    36                           'e': np.ones(5,)}
    37    return specialize(pets_ints_and_array)
    38
    39result = foo()
    40print(result) # ('a', 'bb', 'Meow!', 'Woof!', 'Array(dim=1')

Important things to note about these kinds of dictionaries:

1. They are immutable, use of mutating methods e.g. `.pop()` will result in compilation failure. Read-only static access and read only methods are supported e.g. `len()`.

2. Dynamic access of items is not possible, e.g. `some_dictionary[x]`, for a value `x` which is not a compile time constant. This is because it’s impossible statically determine the type of the item being accessed.

3. Inside the compiler, these dictionaries are actually just named tuples with some extra things added to make them look like they are dictionaries.

4. They cannot be returned to the interpreter from a compiled function.

5. The `.keys()`, `.values()` and `.items()` methods all functionally operate but return tuples opposed to iterables.

### None

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

### 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:

- `contiguous`

- `c_contiguous`

- `f_contiguous`

- `itemsize`

- `nbytes`

- `ndim`

- `readonly`

- `shape`

- `strides`

## Built-in functions

The following built-in functions are supported:

- `abs()`

- `bool`

- `chr()`

- `complex`

- `divmod()`

- `enumerate()`

- `filter()`

- `float`

- `getattr()`: the attribute must be a string literal and the return type cannot be a function type (e.g. `getattr(numpy, 'cos')` is not supported as it returns a function type).

- `hasattr()`

- `hash()` (see Hashing below)

- `int`: only the one-argument form

- `iter()`: only the one-argument form

- `isinstance()`

- `len()`

- `min()`

- `map()`

- `max()`

- `next()`: only the one-argument form

- `ord()`

- `print()`: only numbers and strings; no `file` or `sep` argument

- `range`: The only permitted use of range is as a callable function (cannot pass range as an argument to a jitted function or return a range from a jitted function).

- `repr()`

- `round()`

- `sorted()`: the `key` argument is not supported

- `sum()`

- `str()`

- `type()`: only the one-argument form, and only on some types (e.g. numbers and named tuples)

- `zip()`

### Hashing

The `hash()` built-in is supported and produces hash values for all supported hashable types with the following Python version specific behavior:

Under Python 3, hash values computed by Numba will exactly match those computed in CPython under the condition that the `sys.hash_info.algorithm` is `siphash24` (default).

The `PYTHONHASHSEED` environment variable influences the hashing behavior in precisely the manner described in the CPython documentation.

Note

From NumPy 2.2 onwards, hash values for `numpy.timedelta64` and `numpy.datetime64` instances computed in Numba compiled code do not match the NumPy hash values of the same. Prior to NumPy 2.2, NumPy hash values for `numpy.timedelta64` and `numpy.datetime64` instances were equivalent to their integer value representation. From NumPy 2.2 onwards, their hash value is the same as the hash of the equivalent type from the `datetime` module, Numba does not replicate this behaviour.

## Standard library modules

### `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"`.

### `cmath`

The following functions from the `cmath` module are supported:

- `cmath.acos()`

- `cmath.acosh()`

- `cmath.asin()`

- `cmath.asinh()`

- `cmath.atan()`

- `cmath.atanh()`

- `cmath.cos()`

- `cmath.cosh()`

- `cmath.exp()`

- `cmath.isfinite()`

- `cmath.isinf()`

- `cmath.isnan()`

- `cmath.log()`

- `cmath.log10()`

- `cmath.phase()`

- `cmath.polar()`

- `cmath.rect()`

- `cmath.sin()`

- `cmath.sinh()`

- `cmath.sqrt()`

- `cmath.tan()`

- `cmath.tanh()`

### `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.

### `ctypes`

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

- `ctypes.c_int8`

- `ctypes.c_int16`

- `ctypes.c_int32`

- `ctypes.c_int64`

- `ctypes.c_uint8`

- `ctypes.c_uint16`

- `ctypes.c_uint32`

- `ctypes.c_uint64`

- `ctypes.c_float`

- `ctypes.c_double`

- `ctypes.c_void_p`

### `enum`

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

### `math`

The following functions from the `math` module are supported:

- `math.acos()`

- `math.acosh()`

- `math.asin()`

- `math.asinh()`

- `math.atan()`

- `math.atan2()`

- `math.atanh()`

- `math.ceil()`

- `math.copysign()`

- `math.cos()`

- `math.cosh()`

- `math.degrees()`

- `math.erf()`

- `math.erfc()`

- `math.exp()`

- `math.exp2()`

- `math.expm1()`

- `math.fabs()`

- `math.floor()`

- `math.frexp()`

- `math.gamma()`

- `math.gcd()`

- `math.hypot()`

- `math.isfinite()`

- `math.isinf()`

- `math.isnan()`

- `math.ldexp()`

- `math.lgamma()`

- `math.log()`

- `math.log2()`

- `math.log10()`

- `math.log1p()`

- `math.nextafter()`

- `math.pow()`

- `math.radians()`

- `math.sin()`

- `math.sinh()`

- `math.sqrt()`

- `math.tan()`

- `math.tanh()`

- `math.trunc()`

### `operator`

The following functions from the `operator` module are supported:

- `operator.add()`

- `operator.and_()`

- `operator.eq()`

- `operator.floordiv()`

- `operator.ge()`

- `operator.gt()`

- `operator.iadd()`

- `operator.iand()`

- `operator.ifloordiv()`

- `operator.ilshift()`

- `operator.imatmul()` (Python 3.5 and above)

- `operator.imod()`

- `operator.imul()`

- `operator.invert()`

- `operator.ior()`

- `operator.ipow()`

- `operator.irshift()`

- `operator.isub()`

- `operator.itruediv()`

- `operator.ixor()`

- `operator.le()`

- `operator.lshift()`

- `operator.lt()`

- `operator.matmul()` (Python 3.5 and above)

- `operator.mod()`

- `operator.mul()`

- `operator.ne()`

- `operator.neg()`

- `operator.not_()`

- `operator.or_()`

- `operator.pos()`

- `operator.pow()`

- `operator.rshift()`

- `operator.sub()`

- `operator.truediv()`

- `operator.xor()`

### `functools`

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

### `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.

- `random.betavariate()`

- `random.expovariate()`

- `random.gammavariate()`

- `random.gauss()`

- `random.getrandbits()`: number of bits must not be greater than 64

- `random.lognormvariate()`

- `random.normalvariate()`

- `random.paretovariate()`

- `random.randint()`

- `random.random()`

- `random.randrange()`

- `random.seed()`: with an integer argument only

- `random.shuffle()`: the sequence argument must be a one-dimension Numpy array or buffer-providing object (such as a `bytearray` or `array.array`); the second (optional) argument is not supported

- `random.uniform()`

- `random.triangular()`

- `random.vonmisesvariate()`

- `random.weibullvariate()`

Warning

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

    from numba import njit
    import random

    @njit
    def seed(a):
        random.seed(a)

    @njit
    def rand():
        return random.random()

    # Incorrect seeding
    random.seed(1234)
    print(rand())

    random.seed(1234)
    print(rand())

    # Correct seeding
    seed(1234)
    print(rand())

    seed(1234)
    print(rand())

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.

### `heapq`

The following functions from the `heapq` module are supported:

- `heapq.heapify()`

- `heapq.heappop()`

- `heapq.heappush()`

- `heapq.heappushpop()`

- `heapq.heapreplace()`

- `heapq.nlargest()` : first two arguments only

- `heapq.nsmallest()` : first two arguments only

Note: the heap must be seeded with at least one value to allow its type to be inferred; heap items are assumed to be homogeneous in type.

## Third-party modules

### `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.core.typing.cffi_utils.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.core.typing.cffi_utils.register_module(mod)

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

Inline cffi modules require no registration.