Module 1 · Lesson 3
Array Attributes & Dtypes
Every array carries metadata describing its layout:
.shape— a tuple with the size along each axis.ndim— number of axes (len(shape)).size— total number of elements.dtype— the element type (int64,float64,bool, …).itemsize— bytes per element
NumPy infers a dtype from your data, but mixing an int with a float
upcasts the whole array to float64 — there is no per-element typing.
arr = np.array([[1, 2, 3], [4, 5, 6]])
print("shape: ", arr.shape)
print("ndim: ", arr.ndim)
print("size: ", arr.size)
print("dtype: ", arr.dtype)
print("itemsize:", arr.itemsize, "bytes")
mixed = np.array([1, 2, 3.5]) # one float -> whole array becomes float64
print(mixed.dtype)
Output:
shape: (2, 3)
ndim: 2
size: 6
dtype: int64
itemsize: 8 bytes
float64
Describe an array
Write describe(arr) that returns a dict with keys "shape", "ndim",
"size", and "dtype_name" (the dtype as a string, e.g. "int64") for the
given array.
💡 Hint
str(arr.dtype) gives you the dtype name as a string.
✅ Solution
def describe(arr):
return {
"shape": arr.shape,
"ndim": arr.ndim,
"size": arr.size,
"dtype_name": str(arr.dtype),
}
One more pair of tools before the next exercise. np.floor(x) rounds each
element down to the nearest integer (elementwise) — np.ceil and
np.round work the same way for rounding up / to the nearest. And
np.all(bool_array) collapses a whole boolean array down to a single
True/False: True only if every element is True. np.any is the
mirror image — True if at least one element is True.
print(np.floor(np.array([1.2, 2.9, -0.5]))) # [ 1. 2. -1.]
print(np.all(np.array([True, True, False]))) # False — not all True
print(np.any(np.array([True, True, False]))) # True — at least one True
Output:
[ 1. 2. -1.]
False
True
Safe integer casting
Write to_int_safe(arr) that casts a float array to int64 using
.astype, but raises a ValueError (with any message) if doing so would
silently truncate a non-integer value (e.g. casting 2.5 to 2).
💡 Hint
Compare arr to np.floor(arr) elementwise with ==, then wrap that in np.all(...) to get a single True/False before deciding whether to cast.
✅ Solution
def to_int_safe(arr):
if not np.all(arr == np.floor(arr)):
raise ValueError("array contains non-integer values")
return arr.astype(np.int64)