Hi,
Jessie van Schijndel schrieb am 11.04.22 um 16:22:
> I am trying to create a class which extends numpy arrays. It takes an
> argument *S* which is a dictionary whose keys are integers and values are
> numpy arrays. When I try to create an object from this class I get the
> following TypeError:
>
> *TypeError: expected sequence object with len >= 0 or a single integer*
>
> *NewMatrix.pyx*
>
> import cython
> import numpy as np
> cimport numpy as cnp
> from copy import copy
> from libcpp.map cimport map
>
>
> cdef class NewMatrix(cnp.ndarray):
>
> cdef __new__(cls, map[int, float[:,:]] S):
> shape = (S[0].shape[0], S[0].shape[1])
> obj = np.ndarray.__new__(NewMatrix, shape=shape)
> obj.S = S
> return obj
I guess that your actual code is more complex than this example, but do you
really need to inherit from "ndarray" here? And if so, do you need to do it
in a Cython extension type, or would a Python subclass be ok for you? Maybe
you can use a factory function instead of a new constructor?
The reason why I'm asking (ok, apart from design and simplicity
considerations) is that the "__new__" special method (and especially
something like "cdef __new__") does not actually exist in Cython. It's a
relict that maps to "__cinit__" (which does something entirely different),
but it looks like we don't emit a warning for it. We should.
> *example.py*
>
> from NewMatrix import NewMatrix
> import numpy as np
>
> S = {0: np.array([[1,1], [1,1]])}
> print(S)
> matrix = NewMatrix(S)
I assume that this is where you get the exception. It's actually
interesting that you get this far. We should catch this earlier.
Stefan