Knowing how arrays are stored in memory helps you understand how fast your code runs and how data is accessed.
Understanding array memory layout in NumPy
import numpy as np # Create a numpy array array = np.array([[1, 2, 3], [4, 5, 6]]) # Check if array is stored in C-contiguous order (row-major) is_c_contiguous = array.flags['C_CONTIGUOUS'] # Check if array is stored in Fortran-contiguous order (column-major) is_f_contiguous = array.flags['F_CONTIGUOUS'] # Get the memory layout strides (steps in bytes to move to next element in each dimension) strides = array.strides
C-contiguous means rows are stored one after another in memory.
Fortran-contiguous means columns are stored one after another in memory.
import numpy as np # Empty array empty_array = np.array([]) print(empty_array.flags['C_CONTIGUOUS']) # True because empty arrays are trivially contiguous
import numpy as np # One element array one_element_array = np.array([42]) print(one_element_array.flags['C_CONTIGUOUS']) # True print(one_element_array.strides) # Shows the byte step size
import numpy as np # Transposed array changes memory layout array = np.array([[1, 2, 3], [4, 5, 6]]) transposed_array = array.T print(transposed_array.flags['C_CONTIGUOUS']) # Usually False print(transposed_array.flags['F_CONTIGUOUS']) # Usually True
import numpy as np # Slicing may create non-contiguous views array = np.arange(10) sliced_array = array[::2] print(sliced_array.flags['C_CONTIGUOUS']) # Usually False print(sliced_array.strides)
This program shows how a numpy array is stored in memory, how transposing changes the layout, and how slicing affects contiguity.
import numpy as np # Create a 2D array array = np.array([[10, 20, 30], [40, 50, 60]]) print("Original array:") print(array) # Check memory layout flags print("Is C-contiguous?", array.flags['C_CONTIGUOUS']) print("Is Fortran-contiguous?", array.flags['F_CONTIGUOUS']) print("Strides:", array.strides) # Transpose the array transposed_array = array.T print("\nTransposed array:") print(transposed_array) print("Is C-contiguous?", transposed_array.flags['C_CONTIGUOUS']) print("Is Fortran-contiguous?", transposed_array.flags['F_CONTIGUOUS']) print("Strides:", transposed_array.strides) # Slice the original array with step sliced_array = array[:, ::2] print("\nSliced array (every second column):") print(sliced_array) print("Is C-contiguous?", sliced_array.flags['C_CONTIGUOUS']) print("Is Fortran-contiguous?", sliced_array.flags['F_CONTIGUOUS']) print("Strides:", sliced_array.strides)
Time complexity: Checking memory layout flags is very fast (constant time).
Space complexity: No extra memory is used when checking flags or strides.
Common mistake: Assuming all numpy arrays are stored row-wise (C-contiguous). Transposed or sliced arrays may not be.
Use this knowledge when you want to optimize performance or avoid unexpected data copies.
Arrays can be stored in memory in different orders: row-major (C-contiguous) or column-major (Fortran-contiguous).
Transposing or slicing arrays can change their memory layout and contiguity.
Understanding memory layout helps write faster and more memory-efficient code.