The code:
import sys
import numpy as np
print(f"We are using Python {sys.version}", file=sys.stderr)
print(f"We are using numpy version {np.__version__}", file=sys.stderr) # 2.2.1
def find_non_numpy_floats(x: any) -> bool:
if not (isinstance(x, np.float64)):
print(f"Found non-numpy.float64: {x} of type {type(x)}", file=sys.stderr)
return False
else:
return True
w: np.ndarray = np.zeros((2, 2), dtype=np.float64)
np.vectorize(lambda x: find_non_numpy_floats(x))(w)
assert (np.all(np.vectorize(lambda x: isinstance(x, np.float64))(w))), "try to keep using the numpy floats"
I'm expecting Numpy.zeros to generate an array of Numpy float64
, which are not the same as Python float
if I understand correctly (IEEE 64-bit floats vs something Python specific?)
However the above results in:
We are using Python 3.13.1 (main, Dec 9 2024, 00:00:00) [GCC 14.2.1 20240912 (Red Hat 14.2.1-3)]
We are using numpy version 2.2.1
Found non-numpy.float64: 0.0 of type <class 'float'>
Found non-numpy.float64: 0.0 of type <class 'float'>
Found non-numpy.float64: 0.0 of type <class 'float'>
Found non-numpy.float64: 0.0 of type <class 'float'>
and an assertion error.
Why is that and how can I fix this (and should I want to?)
numpy.vectorize
converts the array to an array of object dtype first:
# Convert args to object arrays first
inputs = [asanyarray(a, dtype=object) for a in args]
I don't know why. I can think of a few plausible reasons, but nothing stands out as a clear motivator.
In any case, converting to object dtype builds an array of ordinary Python scalar objects, rather than an array of NumPy scalars.
It is not possible for an array of float64 dtype to contain ordinary Python floats. An array of float64 dtype has a buffer of raw 8-byte floating-point values, not Python objects. They're not even instances of numpy.float64
- NumPy has to construct numpy.float64
wrapper objects on access if you try to access an individual element.