How to modify a Dict, which value is array

Want to modify a Dict member variable using a class member function, the value of dict is np.array, but an error occurs, the code is

import numba as nb
import numpy as np

spec = [
    ('x', int32),
    ('d', nb.types.DictType(nb.types.unicode_type, nb.float64[:]))
]
@jitclass(spec)
class Cls():
    def __init__(self, x, d):
        self.x = x
        self.d = d
        print('construct')
    def func(self):
        d['1'] = np.zeros(3)
        print('foo')     
    
# @njit
# def foo(d):
#     d['1'] = np.zeros([2, 3])
#     print('foo')
#     return d

@njit    
def bar():
    # d = Dict()
    d = Dict.empty(nb.types.unicode_type, nb.float64[:])
    # d = foo(d)
    c = Cls(2,d)    
    c.func()

bar()

The error message is:

---------------------------------------------------------------------------
TypingError                               Traceback (most recent call last)
Cell In [143], line 32
     29     c = Cls(2,d)    
     30     c.func()
---> 32 bar()
     33 # foo(c.func())

File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/numba/core/dispatcher.py:468, in _DispatcherBase._compile_for_args(self, *args, **kws)
    464         msg = (f"{str(e).rstrip()} \n\nThis error may have been caused "
    465                f"by the following argument(s):\n{args_str}\n")
    466         e.patch_message(msg)
--> 468     error_rewrite(e, 'typing')
    469 except errors.UnsupportedError as e:
    470     # Something unsupported is present in the user code, add help info
    471     error_rewrite(e, 'unsupported_error')

File /Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/numba/core/dispatcher.py:409, in _DispatcherBase._compile_for_args.<locals>.error_rewrite(e, issue_type)
    407     raise e
    408 else:
--> 409     raise e.with_traceback(None)

TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function getitem>) found for signature:
 
 >>> getitem(class(float64), slice<a:b>)
 
There are 22 candidate implementations:
      - Of which 22 did not match due to:
      Overload of function 'getitem': File: <numerous>: Line N/A.
        With argument(s): '(class(float64), slice<a:b>)':
       No match.

During: typing of intrinsic-call at /var/folders/t6/ydb73_8x2slgl6l38dtgksf00000gn/T/ipykernel_69043/638724852.py (27)
During: typing of static-get-item at /var/folders/t6/ydb73_8x2slgl6l38dtgksf00000gn/T/ipykernel_69043/638724852.py (27)

File "../../../../../var/folders/t6/ydb73_8x2slgl6l38dtgksf00000gn/T/ipykernel_69043/638724852.py", line 27:
<source missing, REPL/exec in use?>

Does this error occur because Dict does not know Array shape? How should you change the code?

hi @YiNANzhang it turned out that the problem was not the dictionary, but the array type definition. The getitem operation on float64 could not be performed inside an njit function. I fixed it in this example below. Please also note that there was a missing self. when calling property d. I fixed that too.

import numba as nb
import numpy as np
from numba.typed import Dict

spec = [

    ('x', nb.types.int32),
    ('d', nb.types.DictType(nb.types.unicode_type, nb.float64[:]))
]


@jitclass(spec)
class Cls():
    def __init__(self, x, d):
        self.x = x
        self.d = d
        print('construct')

    def func(self):
        self.d['1'] = np.zeros(3)
        print('foo')

    # @njit


# def foo(d):
#     d['1'] = np.zeros([2, 3])
#     print('foo')
#     return d

arr_ty = nb.float64[:]

@nb.njit
def bar():
    # d = Dict()
    d = Dict.empty(nb.types.unicode_type, arr_ty)
    # d = foo(d)
    c = Cls(2, d)
    c.func()


bar()

Thank you very much for your reply. One question is, why does arr_ty have to be a global variable, and why can’t arr_ty be resolved when defined in Dict.empty()

arr_ty is a type instance. nb.float64[:] is an operation that creates a type instance. Type instances cannot be created inside njit functions. The instance must be created outside. For example, unicode_type is also a type instance, which has been created outside the function, as a module-level variable in nb.types and imported as a module-level variable into this module. arr_ty is the same, it must exist as a variable outside the function and then used.

I see. Thanks very much.