MATLAB Cell Arrays in Python: Lists, Dicts, and NumPy Object Arrays
Cell arrays are MATLAB's heterogeneous container. In Python use lists, dicts, or NumPy object arrays. Learn which to use and how to convert your existing code.
What cell arrays actually are — and why Python has three replacements
A MATLAB cell array is an ordered container that holds elements of different types: numbers, strings, matrices, other cell arrays. Think of it as a matrix where each slot holds an arbitrary value instead of a scalar.
Python has no single equivalent because different uses of cell arrays call for different structures:
| MATLAB cell array pattern | Python replacement |
|---|---|
| {'hello', 'world', 'foo'} — list of strings | ['hello', 'world', 'foo'] — Python list |
| {1, 'text', [1 2 3]} — mixed bag | [1, 'text', np.array([1,2,3])] — Python list |
| C{i} in a for loop | c[i] — list indexing |
| cellfun(@func, C) | [func(x) for x in c] — list comprehension |
| C = cell(m, n) — 2D cell grid | np.empty((m, n), dtype=object) — NumPy object array |
| Named fields per element | [{'name': ..., 'val': ...}] — list of dicts |
The most common case — a list of strings or a list of mixed values — is just a Python list.
Curly brace indexing: C{i} to c[i-1]
MATLAB uses {} for value access and () for sub-array extraction. Python uses [] for both, with the standard 0-based offset:
`matlab
% MATLAB
C = {'apple', 'banana', 'cherry'};
first = C{1}; % 'apple' — 1-based
last = C{end}; % 'cherry'
sub = C(1:2); % {'apple', 'banana'} — still a cell array
`
`python
# Python
c = ['apple', 'banana', 'cherry']
first = c[0] # 'apple' — 0-based
last = c[-1] # 'cherry'
sub = c[0:2] # ['apple', 'banana'] — already a list
`
The golden rule: every C{i} in MATLAB becomes c[i-1] in Python. The converter applies this automatically, but confirm it in any performance-critical loop.
Creating and growing cell arrays
`matlab
% MATLAB — pre-allocate and fill
C = cell(1, 5);
for i = 1:5
C{i} = i^2;
end
% Append C{end+1} = 99;
% 2D cell array
grid = cell(3, 4);
grid{2, 3} = 'hello';
`
`python
# Python — lists grow dynamically (no pre-allocation needed)
c = [i**2 for i in range(1, 6)] # [1, 4, 9, 16, 25]
# Append c.append(99) # in-place c = c + [99] # or create new list
# 2D: use NumPy object array for grid-like access
import numpy as np
grid = np.empty((3, 4), dtype=object)
grid[1, 2] = 'hello' # 0-based: row 1, col 2 = MATLAB row 2, col 3
`
For simple 1D sequences, the Python list is more ergonomic than pre-allocating. Only use a NumPy object array when you need 2D indexed access or want to slice and reshape.
cellfun: mapping a function over every element
cellfun applies a function to every cell. Python uses list comprehensions or map():
`matlab
% MATLAB
words = {'hello', 'world', 'foo'};
lengths = cellfun(@length, words); % [5, 5, 3]
upper = cellfun(@upper, words, 'UniformOutput', false); % {'HELLO','WORLD','FOO'}
`
`python
# Python — list comprehension (preferred)
words = ['hello', 'world', 'foo']
lengths = [len(w) for w in words] # [5, 5, 3]
upper = [w.upper() for w in words] # ['HELLO', 'WORLD', 'FOO']
# Or use map() for simple single-argument functions:
lengths = list(map(len, words))
`
UniformOutput=false → always a list in Python. MATLAB requires UniformOutput=false when the function returns non-scalars; Python lists always hold anything, so there's no equivalent flag.
For NumPy operations across all elements, np.vectorize works but is rarely faster than a comprehension:
`python
import numpy as np
f = np.vectorize(lambda x: x**2 + 1)
result = f(np.array([1, 2, 3, 4])) # array([2, 5, 10, 17])
`
Cell arrays of strings: strcmp, strfind, strsplit
MATLAB's string-in-cell-array idiom maps cleanly to Python lists of str:
`matlab
% MATLAB
labels = {'alpha', 'beta', 'gamma'};
idx = find(strcmp(labels, 'beta')); % 2
match = cellfun(@(s) contains(s,'a'), labels); % [1 0 1]
joined = strjoin(labels, ', '); % 'alpha, beta, gamma'
split = strsplit('a,b,c', ','); % {'a','b','c'}
`
`python
# Python
labels = ['alpha', 'beta', 'gamma']
idx = labels.index('beta') # 1 (0-based)
match = ['a' in s for s in labels] # [True, False, True]
joined = ', '.join(labels) # 'alpha, beta, gamma'
split = 'a,b,c'.split(',') # ['a', 'b', 'c']
# If you need the index (not just True/False):
indices = [i for i, s in enumerate(labels) if 'a' in s] # [0, 2]
`
Nested cell arrays
MATLAB allows cell arrays of cell arrays. Python's lists nest naturally:
`matlab
% MATLAB — nested cells
nested = {{1, 2}, {3, 4}, {5, 6}};
val = nested{2}{1}; % 3
`
`python
# Python — nested lists
nested = [[1, 2], [3, 4], [5, 6]]
val = nested[1][0] # 3 (0-based on both dimensions)
`
For ragged 2D structures (rows of different lengths), a list of lists is the right tool. For rectangular grids where all rows have the same length, consider np.array or np.empty(dtype=object).
Convert your cell array code now
The mental model: everywhere MATLAB uses {} for a heterogeneous container, Python uses []. The conversion is mechanical:
- C{i} → c[i-1]
- C(end) → c[-1]
- cell(1, n) → [None] * n or [] + appends
- cellfun(@f, C) → [f(x) for x in c]
- 2D cell grid → np.empty((m, n), dtype=object)
Paste your MATLAB code into the [free converter at mtopython.com/convert](/convert). The converter handles cell array indexing, cellfun, and cell() constructor calls automatically, shifting indices from 1-based to 0-based throughout.
Free for 50 lines. No account required.
More like this, once a week
New articles on MATLAB-to-Python migration. Short, practical, no fluff — the same tone as the one you just read.