This error happens when code calls .shape on a Python list; use a NumPy array or other size methods instead.
Seeing this message mid-run signals a type mismatch. The code expects an array-like object with a shape attribute, but it received a plain list. In Python, lists are flexible containers, yet they don’t expose shape. NumPy arrays and pandas objects do. That distinction drives both the failure and the fix.
AttributeError: ‘List’ Object Has No Attribute ‘Shape’ — What It Means
The shape attribute represents dimensions for array-like data. NumPy’s ndarray.shape returns a tuple such as (rows, cols), and pandas DataFrames expose .shape for row and column counts. A Python list lacks that attribute altogether, so calling my_list.shape raises the exception.
When the goal is length, a flat list works with len(my_list). When the goal is matrix-like math, convert the list into a NumPy array first, then read arr.shape. That conversion is a one-liner with numpy.asarray() or numpy.array().
Fixing List Object Has No Attribute ‘Shape’ — Common Cases
Quick Checks
- Print The Type — Add
print(type(x))before the failing line. If it shows, you’ve found the mismatch. - Convert Once — Wrap inputs with
np.asarray(x)at the boundary where math begins. This keeps downstream code clean. - Use The Right Size Call — For a 1-D list, use
len(x); for a 2-D list-of-lists, uselen(x)andlen(x[0])after confirming uniform inner lengths.
Case 1 — You Needed An Array, Not A List
Many scientific functions expect NumPy arrays. Convert upfront:
import numpy as np
x = [1, 2, 3, 4]
arr = np.asarray(x) # or np.array(x)
print(arr.shape) # (4,)
np.asarray converts any “array-like” input (including lists and tuples) into an ndarray, which exposes .shape.
Case 2 — You Have A List Of Unequal-Length Rows
A list of lists can’t always become a 2-D array cleanly. If the inner lists differ in length, NumPy creates an object array or fails. Standard math then breaks. Make inner rows uniform before conversion, or pad/truncate as needed.
# Fix ragged rows before converting
rows = [[1, 2, 3], [4, 5]] # ragged
max_len = max(len(r) for r in rows)
fixed = [r + [0]*(max_len - len(r)) for r in rows]
arr = np.asarray(fixed) # now 2-D
print(arr.shape) # (2, 3)
Case 3 — You Really Wanted A DataFrame
If you need labeled rows/columns and table ops, build a pandas DataFrame. DataFrames have .shape and many tools for cleaning and analysis.
import pandas as pd
data = [[10, 20], [30, 40]]
df = pd.DataFrame(data, columns=["a", "b"])
print(df.shape) # (2, 2)
The DataFrame reference confirms that .shape returns a tuple for row and column counts.
Case 4 — Your Library Expects A Tensor
Deep-learning stacks often expect tensors, not lists. Convert lists to tensors or stack per the library docs. If a model returns a list, normalize its output before later layers read attributes like shape.
Case 5 — You Tried To Infer Shape From Heterogeneous Data
Mixing numbers and sequences in the same list can lead to object arrays or failures during shape inference. Normalize the structure first, then convert. Forums and issue trackers show this pitfall in data pipelines.
Correct Ways To Read Dimensions Across Core Types
Different containers expose size in different ways. Pick the call that matches the object you hold.
| Object | What To Call | Notes |
|---|---|---|
| Python list | len(x) |
Lists don’t have shape. Use len, or convert to an array first. |
| NumPy array | x.shape |
Returns a tuple of dimensions like (n, m) for 2-D arrays. |
| pandas DataFrame | x.shape |
Returns (rows, cols) for tabular data. |
Conversion Patterns That Prevent The Error
Reliable pipelines convert early and validate shapes at boundaries. These patterns keep code steady and avoid hard-to-trace crashes.
Convert Lists Into Arrays
- Use
np.asarray()For Zero-Copy When Possible — It returns the input unchanged if it’s already an array; handy in reusable helpers. - Use
np.array()When You Need A Fresh Copy — It creates a new array by default, useful when isolation matters. - Stack Multiple 1-D Arrays — Use
np.stackornp.concatenatealong the correct axis to build a 2-D matrix.
import numpy as np
# 1) idempotent conversion
arr = np.asarray([1, 2, 3]) # array([1, 2, 3])
# 2) ensure a copy
arr2 = np.array([1, 2, 3], copy=True)
# 3) build a matrix from rows
rows = [np.arange(3), np.arange(3, 6)]
mat = np.stack(rows, axis=0) # shape -> (2, 3)
Guard Against Ragged Input
- Validate Inner Lengths — Check that each row shares the same size before stacking; raise a clear error if not.
- Pad Or Truncate To A Target Width — Pick a policy for short or long rows and apply it consistently. That avoids object arrays and keeps math reliable.
- Prefer Typed Arrays For Numeric Work — Homogeneous arrays carry a well-defined
dtypeand predictableshape.
From Error To Fix: A Compact Troubleshooting Flow
Use this flow when the stack trace points to .shape on a list.
- Confirm The Type — Print
type(x). If it’s a list, move to the next steps. - Define The Goal — If you need counts only, use
len. If you need math, convert to an array or DataFrame. - Normalize Structure — For list-of-lists, ensure equal inner lengths or choose a padding policy.
- Convert At The Boundary — Apply
np.asarrayor build a DataFrame before passing the data deeper. - Assert Shapes — Add asserts after conversion, e.g.,
assert arr.ndim == 2, to surface issues early.
Reliable Patterns For Libraries That Expect .shape
Many APIs in scientific Python expect well-shaped arrays. A few habits prevent drift.
Type Boundaries In Your Own Functions
- Accept “Array-Like” — In function signatures, accept sequences but convert internally to arrays using
np.asarray. This keeps your surface flexible and your core strict. - Document Shapes — Note required shapes such as
(n,)or(n, m)in docstrings to set expectations for callers. - Validate Early — Use quick guards:
arr = np.asarray(x); thenassert arr.ndim == 2if a matrix is required.
Working With DataFrames
- Use
df.shapeFor Size — Grab row and column counts for reporting or checks. - Extract Values When Needed — Pass
df.to_numpy()to APIs that require pure arrays; this preserves numeric dtypes and yields a cleanshape. (Shape semantics match NumPy.)
Model Code That Returns Lists
- Normalize Outputs — If a model returns a list of tensors or arrays, stack them with
np.stackor the framework’s equivalent so later layers can readshape. - Stick To One Convention — Decide on
(batch, features)or another shape once, then convert upstream results to match it.
Why Lists Differ From Arrays And DataFrames
A Python list is a general sequence with dynamic sizing and arbitrary objects inside. That flexibility means no fixed dimensional metadata. NumPy arrays are homogeneous blocks with a well-defined dtype and a shape tuple that controls broadcasting and linear algebra. DataFrames wrap arrays with labels and still provide .shape. These differences are baked into their designs.
Putting It Together With Safe, Reusable Snippets
Safe Shape Helper
import numpy as np
def shape_of(x):
"""Return (rows, cols) for 1-D/2-D inputs, converting lists to arrays."""
arr = np.asarray(x) # handles list/tuple/array
if arr.ndim == 0:
return (1, 1)
if arr.ndim == 1:
return (arr.shape[0], 1)
return arr.shape[:2]
Boundary Converter
def to_array_2d(x):
"""Normalize to a 2-D float array."""
arr = np.asarray(x, dtype=float)
if arr.ndim == 1:
arr = arr.reshape(-1, 1) # converts (n,) to (n, 1)
elif arr.ndim > 2:
raise ValueError("expected 1-D or 2-D data")
return arr
Reshape works because arrays carry shape; direct assignment to arr.shape is allowed but the docs favor using reshape for clarity and safety.
When You Must Keep A List
Sometimes a plain list fits the job. You might be collecting events, strings, or nested objects where math isn’t planned. In that case, keep your size calls on len() and avoid .shape. If later steps need numeric work, convert close to the point of use.
- Use
lenFor Count — Flat list count stays stable and fast on large data. - Convert On Demand — Move to arrays only when a library needs
shapeor vectorized math.
The Exact Error, In Lowercase, And Why It Appears
In logs you might see attributeerror: ‘list’ object has no attribute ‘shape’. The message is accurate: the list type has no attribute by that name, while arrays and DataFrames do. Treat it as a signal to convert or to call a size method that matches the container.
If repeated events show attributeerror: ‘list’ object has no attribute ‘shape’ at different points, add type prints or asserts to pin down where lists leak into array-only paths, then normalize at that boundary.
