Skip to content
Back to top
View this page

# Handling `numpy` Object Arrays

class pytools.obj_array.T_co

  alias of TypeVar(‘T_co’, covariant=True)

class pytools.obj_array.ResultT

  alias of TypeVar(‘ResultT’)

class pytools.obj_array.ShapeT

  alias of TypeVar(‘ShapeT’, bound=`tuple`[`int`, …])

class pytools.obj_array.NumpyTypeT

  alias of TypeVar(‘NumpyTypeT’, bound=`np.generic[Any]`)

class pytools.obj_array.ObjectArray

  This is a fake type used to distinguish `numpy.ndarray` instances with a dtype of object for static type checking. Unlike `numpy.ndarray`, this “type” can straightforwardly keep track of its entry type. All instances of this “type” will actually be `numpy.ndarray` at run time. Note that this creates a “universe” of object arrays that’s separate from the usual numpy-generated one. In order to usefully interact in a type-safe manner, object arrays should be “converted” to this “type”.

  Furthermore, `isinstance()` has been customized so as to be accurate for this “type”.

  For now, there is precise typing support for arrays up to two dimensions.

  shape: ShapeT
  dtype: dtype[Any]

  The usual set of operations on `numpy.ndarray` instances works at run time; a subset of these operations are typed. If what you need isn’t typed, please submit a pull request.

  This type is intended to be immutable, and hence covariant in T.

pytools.obj_array.ObjectArray0D

  alias of `ObjectArray`[`tuple`[()], `T_co`]

pytools.obj_array.ObjectArray1D

  alias of `ObjectArray`[`tuple`[`int`], `T_co`]

pytools.obj_array.ObjectArray2D

  alias of `ObjectArray`[`tuple`[`int`, `int`], `T_co`]

pytools.obj_array.ObjectArrayND

  alias of `ObjectArray`[`tuple`[`int`, …], `T_co`]

## Creation

pytools.obj_array.from_numpy(ary: np.ndarray[ShapeT, Any], tp: None = None, /) → ObjectArray[ShapeT, Any]
pytools.obj_array.from_numpy(ary: np.ndarray[ShapeT, Any], tp: type[T_co], /) → ObjectArray[ShapeT, T_co]

pytools.obj_array.to_numpy(ary: ObjectArray[ShapeT, T_co]) → np.ndarray[ShapeT, Any]

pytools.obj_array.new_1d(res_list: np.ndarray[tuple[int], dtype[NumpyTypeT]]) → ObjectArray[tuple[int], NumpyTypeT]
pytools.obj_array.new_1d(res_list: np.ndarray[tuple[int, int], dtype[NumpyTypeT]]) → ObjectArray1D[np.ndarray[tuple[int], dtype[NumpyTypeT]]]
pytools.obj_array.new_1d(res_list: np.ndarray[tuple[int, int, int], dtype[NumpyTypeT]]) → ObjectArray1D[np.ndarray[tuple[int, int], dtype[NumpyTypeT]]]
pytools.obj_array.new_1d(res_list: np.ndarray[tuple[int, ...], dtype[NumpyTypeT]]) → ObjectArray1D[np.ndarray[tuple[int, ...], dtype[NumpyTypeT]]]
pytools.obj_array.new_1d(res_list: Sequence[T_co]) → ObjectArray[tuple[int], T_co]

  Create a one-dimensional object array from res_list. This differs from `numpy.array(res_list, dtype=object)` by whether it tries to determine its shape by descending into nested array-like objects. Consider the following example:

      >>> import numpy as np
      >>> a = np.array([np.arange(5), np.arange(5)], dtype=object)
      >>> a
      array([[0, 1, 2, 3, 4],
             [0, 1, 2, 3, 4]], dtype=object)
      >>> a.shape
      (2, 5)
      >>> # meanwhile:
      >>> from pytools.obj_array import new_1d
      >>> b = new_1d([np.arange(5), np.arange(5)])
      >>> b
      array([array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4])], dtype=object)
      >>> b.shape
      (2,)

  In some settings (such as when the sub-arrays are large and/or live on a GPU), the recursive behavior of `numpy.array()` can be undesirable.

  Added in version 2025.2.2: Renamed from `make_obj_array`.

pytools.obj_array.flat(*args: ObjectArray[ShapeT, T_co] | list[T_co] | T_co) → ObjectArray[tuple[int], T_co]

  Return a one-dimensional flattened object array consisting of elements obtained by ‘flattening’ args as follows:

  - The first axis of any non-subclassed object arrays will be flattened into the result.

  - Instances of `list` will be flattened into the result.

  - Any other type will appear in the list as-is.

pytools.obj_array.stack(arrays: Sequence[ObjectArray[ShapeT, T_co]], /, *, axis: Literal[0] = 0) → ObjectArray[tuple[int, Unpack[ShapeT]], T_co]

  Added in version 2025.2.2.

pytools.obj_array.concatenate(arrays: Sequence[ObjectArray[tuple[int, Unpack[ShapeT]], T_co]], /, *, axis: Literal[0] = 0) → ObjectArray[tuple[int, Unpack[ShapeT]], T_co]

  Added in version 2025.2.2.

pytools.obj_array.trace(array: ObjectArray[tuple[int, int], T_co], /) → T_co

  Added in version 2025.2.2.

## Mapping

pytools.obj_array.vectorize(f: Callable[[T_co], ResultT], ary: ObjectArray[ShapeT, T_co]) → ObjectArray[ShapeT, ResultT]
pytools.obj_array.vectorize(f: Callable[[T_co], ResultT], ary: T_co) → ResultT

  Apply the function f to all entries of the object array ary. Return an object array of the same shape consisting of the return values. If ary is not an object array, return `f(ary)`.

  Note

  This function exists because `numpy.vectorize` suffers from the same issue described under `new_1d()`.

pytools.obj_array.vectorize_n_args(f, *args)

  Apply the function f elementwise to all entries of any object arrays in args. All such object arrays are expected to have the same shape (but this is not checked). Equivalent to an appropriately-looped execution of:

      result[idx] = f(obj_array_arg1[idx], arg2, obj_array_arg3[idx])

  Return an object array of the same shape as the arguments consisting of the return values of f.

  Note

  This function exists because `numpy.vectorize` suffers from the same issue described under `new_1d()`.

## Numpy workarounds

These functions work around a long-standing, annoying numpy issue.

pytools.obj_array.obj_array_real(ary)

pytools.obj_array.obj_array_imag(ary)

pytools.obj_array.obj_array_real_copy(ary)

pytools.obj_array.obj_array_imag_copy(ary)