NumPy array.tolist(): Convert Arrays to Python Lists

Quick answer: Call array.tolist() to convert a NumPy array into nested Python lists and compatible Python scalar values. Use it at an interoperability boundary such as JSON preparation, not as a replacement for vectorized NumPy operations.

NumPy array tolist diagram showing ndarray shape and dtype, nested Python lists, JSON boundaries, and conversion policies
tolist() is an interoperability boundary, not a faster replacement for NumPy operations; convert once when the next system needs lists.

array.tolist() converts a NumPy array into normal Python objects. A one-dimensional array becomes a list. A two-dimensional array becomes a nested list. A zero-dimensional array becomes a Python scalar.

This method is useful when data must leave NumPy and move into plain Python code, JSON output, web APIs, or test assertions. It is not the best choice when you still need fast vectorized NumPy operations, because lists do not keep NumPy’s array behavior.

Treat tolist() as a boundary tool. Keep arrays as arrays while computing, filtering, reshaping, or aggregating. Convert only when the next layer expects plain Python containers.

The official NumPy ndarray.tolist documentation explains how array items are converted to nearest compatible Python scalar objects. Related NumPy references include asarray, array, and NumPy data types.

Convert A 1D Array

For a one-dimensional array, tolist() returns a flat Python list.

import numpy as np

arr = np.array([10, 20, 30])
items = arr.tolist()

print(items)
print(type(items))

The result is a normal list, so list methods and plain Python loops work as expected.

This is often helpful for small results, configuration output, or code that must call a library that does not understand NumPy arrays.

Convert A 2D Array

For a two-dimensional array, tolist() preserves the row structure as nested lists.

import numpy as np

matrix = np.array([
    [1, 2, 3],
    [4, 5, 6],
])

rows = matrix.tolist()

print(rows)
print(rows[0])

This is useful when sending table-like data to an API or when comparing expected rows in tests.

The nesting follows the original array shape. A three-dimensional array would produce lists inside lists inside lists, which can become hard to inspect by hand.

Python Pool infographic showing a NumPy array, dimensions, nested rows, dtype, and tolist conversion
Array shape: A NumPy array, dimensions, nested rows, dtype, and tolist conversion.

Handle A Scalar Array

A zero-dimensional NumPy array becomes a Python scalar rather than a list.

import numpy as np

score = np.array(42)
plain_score = score.tolist()

print(plain_score)
print(type(plain_score))

This behavior is correct but easy to forget. If the caller always expects a list, handle scalar arrays before conversion.

For APIs, document whether a scalar result is allowed. Predictable output shape is more important than saving one line of conversion code.

Prepare JSON Output

The standard json module cannot serialize many NumPy objects directly. Convert arrays to lists first.

import json
import numpy as np

payload = {
    "name": "samples",
    "values": np.array([0.1, 0.2, 0.3]).tolist(),
}

text = json.dumps(payload)
print(text)

For nested arrays, the same method produces nested lists that JSON can encode.

For very large arrays, JSON output can become expensive and bulky. Consider summaries, pagination, binary formats, or files when the payload is large.

Python Pool infographic mapping NumPy array values through tolist into nested Python lists
Convert values: NumPy array values through tolist into nested Python lists.

Recreate An Array With dtype

When converting back to NumPy, pass dtype if the exact type matters.

import numpy as np

arr = np.array([1, 2, 3], dtype=np.int16)
items = arr.tolist()

restored = np.array(items, dtype=np.int16)

print(restored)
print(restored.dtype)

The list does not remember the original NumPy dtype. Recreate that dtype deliberately when it matters for storage, memory, or downstream libraries.

This is especially important for small integer types, unsigned values, and precise floating-point formats. Plain Python objects do not carry the same dtype metadata.

Python Pool infographic comparing NumPy scalars, Python scalars, object values, and serializable lists
Type changes: NumPy scalars, Python scalars, object values, and serializable lists.

Compare list() And tolist()

list(array) only converts the outer level. tolist() converts nested NumPy arrays too.

import numpy as np

matrix = np.array([[1, 2], [3, 4]])

outer_only = list(matrix)
fully_plain = matrix.tolist()

print(type(outer_only[0]))
print(type(fully_plain[0]))

For nested data, prefer tolist() when the goal is plain Python lists all the way down.

This distinction matters in tests. A shallow list conversion may still contain NumPy arrays, so equality checks can behave differently than expected.

Practical Guidance

Use tolist() at boundaries: JSON output, API payloads, snapshots, simple assertions, and places where code no longer needs NumPy operations. Keep arrays as arrays while doing numeric work.

Be aware that NumPy scalar types become close Python scalar types. That is usually helpful, but converting back may not preserve the exact dtype unless you request it.

For large arrays, conversion can allocate a lot of Python objects. If the next step can handle NumPy arrays, avoid conversion and pass the array directly.

The safest workflow is to convert only at the boundary, document whether nested lists are expected, and restore dtype explicitly when converting back to NumPy.

That keeps numeric code fast while still giving APIs and plain Python callers the format they expect.

When returning lists from a function, document the shape of the result. A flat list, nested row list, and scalar value are different contracts. Clear shape expectations make callers easier to test and reduce surprises when an array changes from one dimension to two.

This matters most at package and API boundaries.

Python Pool infographic testing zero dimensions, strings, NaN, precision, and round trips
List checks: Zero dimensions, strings, NaN, precision, and round trips.

Use tolist At A Boundary

tolist() creates ordinary Python containers, so it is useful when an API, serializer, or template expects lists rather than an ndarray. The output preserves the array’s nesting shape, but it no longer carries NumPy’s dtype, strides, broadcasting behavior, or methods.

import json
import numpy as np

values = np.array([[1, 2], [3, 4]], dtype=np.int64)
payload = {"values": values.tolist()}
print(json.dumps(payload))

Do Not Convert Too Early

Keep data as an ndarray while filtering, reshaping, multiplying, or calculating statistics. Converting to lists too early can add Python-level loops and lose dtype information. Convert once when the next system genuinely requires Python-native containers.

When round-tripping through JSON, remember that JSON has fewer types than NumPy. NaN, infinities, complex values, datetime values, and object arrays need an explicit serialization policy instead of relying on a blind conversion.

Test the converted payload at the exact boundary where another library or service will consume it.

For array conversion workflows, compare tolist() with asarray() and DataFrame conversion. Read numpy asarray and numpy array to pandas dataframe for the related workflow.

Frequently Asked Questions

What does NumPy array.tolist() do?

tolist() converts an ndarray into a possibly nested Python list and converts array scalar values to compatible Python scalars where possible.

Does tolist() preserve the NumPy dtype?

No. The result is made of Python containers and scalar values, so dtype metadata and NumPy array behavior are not carried across.

How do I convert a NumPy array for JSON?

Call tolist() and place the resulting Python-native lists and scalars in the JSON payload, while defining policies for NaN, complex, or other unsupported values.

Should I call tolist() before NumPy calculations?

Usually no. Keep data as an ndarray for vectorized operations and convert only at the API, serializer, or template boundary that requires Python lists.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted