Swap rows and columns of a 2×3 matrix to produce a 3×2 result. A pre-allocated output matrix is filled cell by cell with out[j][i] = a[i][j]. The trace shows out filling column by column from the source rows, making the index swap visible before the one-attribute NumPy version.

By hand

Pre-allocate out as a 3×2 zero matrix. Loop over each row i and column j of a; assign out[j][i] = a[i][j]. Swapping the index order flips the dimensions.

naive.py
Replay: real traced execution (multi-file project)
a = [[1, 2, 3], [4, 5, 6]]
rows = len(a)
cols = len(a[0])
out = [[0, 0], [0, 0], [0, 0]]
for i in range(rows):
    for j in range(cols):
        out[j][i] = a[i][j]
print('RESULT:', out)
  1. a ← [[1, 2, 3], [4, 5, 6]]

    1a = [[1, 2, 3], [4, 5, 6]]2rows = len(a)
    values this step[[1, 2, 3], [4, 5, 6]]a
  2. rows ← 2

    1a = [[1, 2, 3], [4, 5, 6]]2rows = len(a)3cols = len(a[0])
    values this step2rows
  3. cols ← 3

    2rows = len(a)3cols = len(a[0])4out = [[0, 0], [0, 0], [0, 0]]
    values this step3cols
  4. out ← [[0, 0], [0, 0], [0, 0]]

    3cols = len(a[0])4out = [[0, 0], [0, 0], [0, 0]]5for i in range(rows):
    values this step[[0, 0], [0, 0], [0, 0]]out
  5. i ← 0

    4out = [[0, 0], [0, 0], [0, 0]]5for i in range(rows):6    for j in range(cols):
    values this step0i
  6. j ← 0

    5for i in range(rows):6    for j in range(cols):7        out[j][i] = a[i][j]
    values this step0j
  7. out ← [[1, 0], [0, 0], [0, 0]]

    6    for j in range(cols):7        out[j][i] = a[i][j]8print('RESULT:', out)
    values this step[[0, 0], [0, 0], [0, 0]] [[1, 0], [0, 0], [0, 0]]out
  8. j ← 1

    5for i in range(rows):6    for j in range(cols):7        out[j][i] = a[i][j]
    values this step0 1j
  9. out ← [[1, 0], [2, 0], [0, 0]]

    6    for j in range(cols):7        out[j][i] = a[i][j]8print('RESULT:', out)
    values this step[[1, 0], [0, 0], [0, 0]] [[1, 0], [2, 0], [0, 0]]out
  10. j ← 2

    5for i in range(rows):6    for j in range(cols):7        out[j][i] = a[i][j]
    values this step1 2j
  11. out ← [[1, 0], [2, 0], [3, 0]]

    6    for j in range(cols):7        out[j][i] = a[i][j]8print('RESULT:', out)
    values this step[[1, 0], [2, 0], [0, 0]] [[1, 0], [2, 0], [3, 0]]out
  12. for j in range(cols):

    5for i in range(rows):6    for j in range(cols):7        out[j][i] = a[i][j]
  13. i ← 1

    4out = [[0, 0], [0, 0], [0, 0]]5for i in range(rows):6    for j in range(cols):
    values this step0 1i
  14. j ← 0

    5for i in range(rows):6    for j in range(cols):7        out[j][i] = a[i][j]
    values this step2 0j
  15. out ← [[1, 4], [2, 0], [3, 0]]

    6    for j in range(cols):7        out[j][i] = a[i][j]8print('RESULT:', out)
    values this step[[1, 0], [2, 0], [3, 0]] [[1, 4], [2, 0], [3, 0]]out
  16. j ← 1

    5for i in range(rows):6    for j in range(cols):7        out[j][i] = a[i][j]
    values this step0 1j
  17. out ← [[1, 4], [2, 5], [3, 0]]

    6    for j in range(cols):7        out[j][i] = a[i][j]8print('RESULT:', out)
    values this step[[1, 4], [2, 0], [3, 0]] [[1, 4], [2, 5], [3, 0]]out
  18. j ← 2

    5for i in range(rows):6    for j in range(cols):7        out[j][i] = a[i][j]
    values this step1 2j
  19. out ← [[1, 4], [2, 5], [3, 6]]

    6    for j in range(cols):7        out[j][i] = a[i][j]8print('RESULT:', out)
    values this step[[1, 4], [2, 5], [3, 0]] [[1, 4], [2, 5], [3, 6]]out
  20. for j in range(cols):

    5for i in range(rows):6    for j in range(cols):7        out[j][i] = a[i][j]
  21. for i in range(rows):

    4out = [[0, 0], [0, 0], [0, 0]]5for i in range(rows):6    for j in range(cols):
  22. stdout ← RESULT: [[1, 4], [2, 5], [3, 6]]

    7        out[j][i] = a[i][j]8print('RESULT:', out)
    values this stepRESULT: [[1, 4], [2, 5], [3, 6]]stdout

With NumPy

arr.T returns the transpose as a view — no data is copied. The snapshot shows the original (2, 3) shape and the transposed (3, 2) shape.

library.py
import numpy as np

a = [[1, 2, 3], [4, 5, 6]]
arr = np.array(a)
result = arr.T
print('arr: shape:', arr.shape, 'dtype:', arr.dtype, 'values:', arr.tolist())
print('result: shape:', result.shape, 'dtype:', result.dtype, 'values:', result.tolist())
print('RESULT:', result.tolist())
arr: shape: (2, 3) dtype: int64 values: [[1, 2, 3], [4, 5, 6]]
result: shape: (3, 2) dtype: int64 values: [[1, 4], [2, 5], [3, 6]]
RESULT: [[1, 4], [2, 5], [3, 6]]

Implementation notes

  • arr.T is a view: it shares memory with arr. Modifying arr.T modifies arr. To get an independent copy use arr.T.copy().
  • Transposing swaps axes: a (rows, cols) array becomes (cols, rows). For higher-dimensional arrays arr.T reverses all axes; use np.transpose(arr, axes) to specify a custom axis permutation.
  • Transposing is common before a matrix multiply: if A is (m, n) and you want A.T @ A you get a (n, n) square matrix, useful in linear regression normal equations.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.