What is the difference between a NumPy array and a Python list?
Short answer
A NumPy array holds one fixed type in a compact block of memory and supports fast whole-array maths, while a list holds any mix of objects and grows flexibly. Use arrays for numeric computation and lists for general collections.
The short version
A NumPy array stores elements of a single fixed type in one contiguous block of memory, which makes numeric operations across the whole array fast and lets you do arithmetic on it directly. A Python list holds a flexible, mixed collection of objects and grows easily but has no built-in maths. Use arrays for numeric computation and lists for general-purpose collections.
Arithmetic works differently
import numpy as np
a = np.array([1, 2, 3])
print(a * 2) # [2 4 6], element-wise
lst = [1, 2, 3]
print(lst * 2) # [1, 2, 3, 1, 2, 3], list repetition
On an array, * 2 multiplies every element. On a list, * 2 repeats the list. This difference catches people out constantly, and it is the clearest sign of which type you are holding.
Why arrays are faster for numbers
An array packs its numbers into a single typed memory block, so NumPy can run operations in compiled code over the whole block at once. A list stores pointers to separate Python objects scattered in memory, so looping over it pays Python's per-element overhead. For large numeric work the array is dramatically faster and uses less memory.
Why lists are more flexible
A list can hold anything, mixed freely, and change type as it grows.
mixed = [1, "two", 3.0, [4, 5]] # perfectly fine
An array cannot do this cleanly; forcing mixed types into one either upcasts everything (numbers become strings) or falls back to a slow object array that loses the speed benefit. So for heterogeneous or general data, a list is the right tool.
The fixed-type consequence
Because an array has one dtype, assigning a value of another type is coerced to fit. Putting a float into an integer array truncates it, and there is no error.
arr = np.array([1, 2, 3]) # int
arr[0] = 9.9
print(arr[0]) # 9, silently truncated
This is a common surprise. If you need floats, create the array as float from the start (np.array([1, 2, 3], dtype=float)).
Choosing between them
Reach for a NumPy array when you have numbers and want fast, whole-array maths, statistics, or linear algebra. Reach for a list when you have a general collection, mixed types, or you are frequently appending items of unknown type. Many programs use both: lists to gather and organise, arrays to compute.
The pandas connection
A pandas Series is built on a NumPy array, so it inherits the fast, typed, whole-column behaviour. That is why column arithmetic in pandas is quick and why the same fixed-type rules apply. Understanding the array underneath explains a lot of how pandas behaves.