The ndarray: NumPy

Reviewed & published by Brayan K

The ndarray is NumPy's central data structure — a homogeneous, fixed-type, contiguous grid of values that can have any number of dimensions, from a single row of numbers to a multi-dimensional cube of data.

Part of the free NumPy course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll see exactly what makes the ndarray special, how 1D, 2D, and 3D arrays are structured, why it beats a Python list, and how to read its dtype and dimensions.

What You'll Learn in This Lesson

1 What Exactly Is an ndarray?

The ndarray (short for n-dimensional array) is a grid of values that are all the same type and laid out in one continuous block of memory. Three properties define it:

Because the layout is so regular, NumPy can run math on the whole array in compiled C — no Python loop required.

import numpy as np

# Build a 1D ndarray from a Python list
arr = np.array([10, 20, 30, 40])

print(arr)            # [10 20 30 40]
print(type(arr))      # <class 'numpy.ndarray'>
print(arr.dtype)      # int64  (one dtype for every element)

# ✅ Expected output:
# [10 20 30 40]
# <class 'numpy.ndarray'>
# int64

Expected output: the array [10 20 30 40], its type numpy.ndarray, and a single dtype such as int64.

2 1D vs 2D vs 3D Arrays

An ndarray can have any number of dimensions, called axes. The .ndim attribute tells you how many there are: a flat list of numbers is 1D, a table or matrix is 2D, and a stack of matrices is 3D.

import numpy as np

a1 = np.array([1, 2, 3])                       # 1D
a2 = np.array([[1, 2, 3], [4, 5, 6]])          # 2D
a3 = np.array([[[1, 2], [3, 4]],
               [[5, 6], [7, 8]]])              # 3D

print(a1.ndim)   # 1
print(a2.ndim)   # 2
print(a3.ndim)   # 3

print(a2)
# [[1 2 3]
#  [4 5 6]]

# ✅ Expected output:
# 1
# 2
# 3
# [[1 2 3]
#  [4 5 6]]

Expected output: 1, 2, 3, then the 2×3 matrix. Each extra level of nested lists adds one dimension.

3 ndarray vs Python List

A Python list is flexible — it can hold mixed types and grow freely — but that flexibility costs speed and memory. An ndarray is the opposite: one fixed dtype, contiguous storage, and vectorized math. Notice how building an array from mixed numbers forces a single common dtype.

import numpy as np

# A Python list keeps each value's own type
py_list = [1, 2.5, 3]
print(type(py_list[0]), type(py_list[1]))  # <class 'int'> <class 'float'>

# A NumPy array is homogeneous: it upcasts everything to ONE dtype
arr = np.array([1, 2.5, 3])
print(arr)         # [1.  2.5 3. ]
print(arr.dtype)   # float64  -> the ints became floats

# Vectorized math works on the whole array, no loop
print(arr * 2)     # [2. 5. 6.]

# ✅ Expected output:
# <class 'int'> <class 'float'>
# [1.  2.5 3. ]
# float64
# [2. 5. 6.]

Expected output: the list keeps an int and a float, but the array prints [1. 2.5 3. ] with dtype float64 because every element must share one type.

4 Accessing Elements

You read values out of an ndarray with square-bracket indexing, just like a list. In a 1D array arr[0] is the first element. In a 2D array you give a row and a column with arr[row, col].

import numpy as np

arr = np.array([100, 200, 300, 400])

print(arr[0])    # 100  -> first element
print(arr[2])    # 300  -> third element
print(arr[-1])   # 400  -> last element (negative index)

grid = np.array([[1, 2, 3],
                 [4, 5, 6]])

print(grid[0, 1])  # 2  -> row 0, column 1
print(grid[1, 2])  # 6  -> row 1, column 2

# ✅ Expected output:
# 100
# 300
# 400
# 2
# 6

Expected output: 100, 300, 400 from the 1D array, then 2 and 6 from the 2D grid using [row, col].

🎯 YOUR TURN: Fill in the Blanks

Replace each ___ so the program builds a 2D array and prints its dimensions and one element.

import numpy as np

grid = np.___([[7, 8, 9],
               [1, 2, 3]])     # fill in the function that builds an array

print(grid.___)                # fill in the attribute for number of dimensions -> 2

print(grid[1, ___])            # fill in the column index to print 3

Expected output: 2 then 3. (Answers: array, ndim, 2.)

⚠️ Common Errors & Quick Reference

❌ IndexError: index 4 is out of bounds for axis 0 with size 4

You asked for an index past the end. An array of length 4 has valid indices 0 to 3.

✅ Fix: use indices from 0 to len(arr) - 1, or use arr[-1] for the last item.

❌ Surprise: my ints turned into floats / strings

An ndarray is homogeneous, so mixed inputs are upcast to one common dtype.

✅ Fix: keep inputs the same type, or set the dtype explicitly with dtype=.

TaskCode
Make a 1D arraynp.array([1, 2, 3])
Number of dimensionsarr.ndim
Element data typearr.dtype
Element in 2D arrayarr[row, col]

🏆 Mini Challenge: Inspect a Matrix

Create a 2D array of test scores, then report its dimensions, dtype, and the value in the middle.

import numpy as np

scores = np.array([[88, 92, 79],
                   [95, 70, 100]])

print("Dimensions:", scores.ndim)   # Dimensions: 2
print("Dtype:", scores.dtype)       # Dtype: int64
print("Center value:", scores[0, 1])  # Center value: 92

# ✅ Expected output:
# Dimensions: 2
# Dtype: int64
# Center value: 92

❓ Frequently Asked Questions

Lesson complete — you understand the ndarray!

You now know that the ndarray is homogeneous, fixed-type, and contiguous, how 1D, 2D, and 3D arrays are structured, and how to read elements, .ndim, and .dtype.

Practice quiz

What does ndarray stand for?

  • n-dimensional array
  • named array
  • nested array
  • numeric array

Answer: n-dimensional array. ndarray is short for n-dimensional array, NumPy's central data structure.

Which word describes an ndarray holding one single dtype for every element?

  • Heterogeneous
  • Homogeneous
  • Dynamic
  • Sparse

Answer: Homogeneous. An ndarray is homogeneous: every element shares one fixed dtype.

What does arr.ndim return for np.array([[[1,2],[3,4]],[[5,6],[7,8]]])?

  • 1
  • 2
  • 3
  • 4

Answer: 3. Three nested bracket levels make it a 3D array, so ndim is 3.

What dtype does np.array([1, 2.5, 3]) have?

  • int64
  • object
  • float64
  • str

Answer: float64. Mixed ints and floats upcast to one common dtype: float64.

How do you read row 1, column 2 of a 2D array named grid?

  • grid(1, 2)
  • grid[1][2] only
  • grid{1,2}
  • grid[1, 2]

Answer: grid[1, 2]. NumPy uses grid[row, col], so grid[1, 2] reads row 1, column 2.

Which attribute gives an ndarray's element data type?

  • arr.dtype
  • arr.type
  • arr.kind
  • arr.format

Answer: arr.dtype. arr.dtype reports the single shared data type of the elements.

How is an ndarray different from a Python list?

  • It can hold any mix of types
  • It is scattered in memory
  • It holds one fixed dtype in contiguous memory
  • It cannot do math

Answer: It holds one fixed dtype in contiguous memory. An ndarray is homogeneous and contiguous, unlike a flexible Python list.

What is arr[-1] for arr = np.array([100, 200, 300, 400])?

  • 100
  • an error
  • 300
  • 400

Answer: 400. Negative indexing counts from the end, so arr[-1] is the last value, 400.

What does .ndim return for a flat 1D array?

  • 1
  • 0
  • the length
  • 2

Answer: 1. A flat list of numbers has a single axis, so ndim is 1.

Why can NumPy run math on a whole array without a Python loop?

  • It rewrites your code
  • Its regular contiguous layout lets compiled C scan it
  • It uses a database
  • It caches results

Answer: Its regular contiguous layout lets compiled C scan it. The fixed-type contiguous layout lets NumPy run the math in compiled C.

Continue this course

Frequently asked questions

What is the ndarray in NumPy?

The ndarray (n-dimensional array) is NumPy's central data structure. It is a grid of values, all of the same data type, stored in one contiguous block of memory. Every NumPy operation works on ndarrays.

How is a NumPy ndarray different from a Python list?

A Python list can hold mixed types and is scattered across memory, while an ndarray holds a single fixed dtype in contiguous memory. That makes ndarrays smaller, faster, and able to do vectorized math without loops.

Can a NumPy array hold different types like a list?

No. An ndarray is homogeneous — every element shares one dtype. If you build an array from mixed values, NumPy upcasts them all to a single common type (for example, ints become floats, or everything becomes strings).

What does ndim tell me about an array?

The .ndim attribute returns the number of dimensions (axes) of the array. A 1D array has ndim 1, a 2D matrix has ndim 2, and a 3D array (like a stack of matrices) has ndim 3.