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.
Practice
C-contiguous?Solution
Step 1: Understand memory layout types
C-contiguous means the array is stored in row-major order, where rows are stored sequentially in memory.Step 2: Compare with other layouts
Fortran-contiguous arrays store columns sequentially, not rows.Final Answer:
The array is stored in row-major order, meaning rows are stored one after another in memory. -> Option CQuick Check:
C-contiguous = row-major order [OK]
- Confusing C-contiguous with Fortran-contiguous
- Thinking C-contiguous means compressed storage
- Assuming C-contiguous means column-major order
a is stored in Fortran-contiguous order?Solution
Step 1: Recall NumPy flags for memory layout
NumPy arrays have aflagsattribute withf_contiguousto check Fortran order.Step 2: Identify correct syntax
a.flags.f_contiguousreturns True if arrayais Fortran-contiguous.Final Answer:
a.flags.f_contiguous -> Option DQuick Check:
Check Fortran order with a.flags.f_contiguous [OK]
- Using non-existent functions like np.isfortran
- Confusing C-contiguous and Fortran-contiguous flags
- Trying to call methods that don't exist on arrays
import numpy as np arr = np.array([[1, 2, 3], [4, 5, 6]]) transposed = arr.T print(transposed.flags.c_contiguous)
What will be the output?
Solution
Step 1: Understand the original array layout
Original arrayarris C-contiguous by default (row-major).Step 2: Analyze the transpose operation
Transposingarr.Tchanges memory layout to non-C-contiguous because rows and columns swap.Step 3: Check the flag after transpose
transposed.flags.c_contiguouswill be False since the transpose breaks row-major order.Final Answer:
False -> Option BQuick Check:
Transpose breaks C-contiguity = False [OK]
- Assuming transpose keeps C-contiguity True
- Confusing c_contiguous with f_contiguous
- Expecting an error instead of a boolean
import numpy as np arr = np.arange(6).reshape(2, 3) sliced = arr[:, 1:3] print(sliced.flags.c_contiguous)
Why might
sliced.flags.c_contiguous be False?Solution
Step 1: Understand slicing behavior
Slicing often returns a view, which may not be stored continuously in memory.Step 2: Check memory layout after slicing
The slicearr[:, 1:3]selects columns 1 and 2, which may not be contiguous in row-major order.Step 3: Explain why c_contiguous is False
Because the slice skips some elements in memory, the resulting view is not C-contiguous.Final Answer:
Because slicing can create views that are not stored continuously in memory. -> Option AQuick Check:
Slicing can break contiguity = False [OK]
- Thinking slicing always returns a copy
- Assuming reshape changes memory layout to Fortran order by default
- Believing arange arrays are never contiguous
Solution
Step 1: Recall how to specify memory order in NumPy
Use theorderparameter with value 'F' to create Fortran-contiguous arrays.Step 2: Analyze each option
np.zeros((1000, 1000), order='F')usesorder='F', which is correct.np.zeros((1000, 1000), order='C')uses 'C' (row-major).np.zeros((1000, 1000)).T.copy()transposes a C-contiguous array and copies it into a new C-contiguous array by default.np.zeros((1000, 1000), fortran=True)uses an invalid parameter.Final Answer:
np.zeros((1000, 1000), order='F') -> Option AQuick Check:
Use order='F' to create Fortran order arrays [OK]
- Using order='C' instead of 'F'
- Trying to transpose to get Fortran order
- Using invalid parameters like fortran=True
Ready to prove it?
Pass the test and this pattern moves unknown
