Skip to content
Python Basics: Keeping Numeric Samples in an array

Python Basics: Keeping Numeric Samples in an array

October 13, 2026

A series of measurements often contains one kind of number. Python’s standard-library array module stores these values in a compact numeric sequence. It is useful when you want ordinary sequence operations with a specific storage type.

Before you start

These three independent scripts were tested on Linux with Bash, Python 3.12.14 and Python 3.13.5. No extra packages or environment variables are needed. Commands use python3; substitute python3.13 to run the other tested interpreter.

Create a fresh working directory and keep this Bash session open:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Save each UTF-8 source block below here using its stated filename. Avoid array.py, which would shadow the standard-library module. The scripts print results without creating data files or accessing the network.

Add and inspect measurements

Save as demo_array_samples.py:

from array import array

samples = array("d", [18.5, 19.0, 20.5])
samples.append(21.0)
samples.extend([22.0, 23.0])
print("Samples:", samples.tolist())
print("Last three:", samples[-3:].tolist())
print("Mean:", sum(samples) / len(samples))

for readings in (samples, array("d")):
    if readings:
        print("Maximum:", max(readings))
    else:
        print("No samples yet")

Run it:

python3 demo_array_samples.py

Output:

Samples: [18.5, 19.0, 20.5, 21.0, 22.0, 23.0]
Last three: [21.0, 22.0, 23.0]
Mean: 20.666666666666668
Maximum: 23.0
No samples yet

The "d" type code selects C double storage. Slicing returns another array; tolist() makes the displayed values familiar. Check for an empty collection before taking its maximum or dividing by its length. Floating-point rounding still applies.

Reject unsuitable values

Save as demo_array_bounds.py:

from array import array

levels = array("B", [0, 128, 255])
for value in (-1, 256, "bright"):
    try:
        levels.append(value)
    except (OverflowError, TypeError) as error:
        print(f"Rejected {value!r}: {type(error).__name__}")

levels[1:2] = array("B", [64, 192])
print("Levels:", levels.tolist())

try:
    levels[0:1] = [32]
except TypeError:
    print("Slice replacement needs an array with the same type code")

Run it:

python3 demo_array_bounds.py

Output:

Rejected -1: OverflowError
Rejected 256: OverflowError
Rejected 'bright': TypeError
Levels: [0, 64, 192, 255]
Slice replacement needs an array with the same type code

On the tested Linux systems, "B" stores unsigned bytes from 0 to 255. These deliberately caught errors demonstrate bounds and type checks. They do not end the script. Slice assignment also requires a matching array type, even when a plain list contains valid integers.

Round-trip an in-memory buffer

Save as demo_array_buffer.py:

from array import array

original = array("h", [-100, 0, 100])
payload = original.tobytes()
restored = array("h")
restored.frombytes(payload)

print("Restored:", restored.tolist())
print("Equal:", restored == original)
print("Payload size matches:", len(payload) == len(original) * original.itemsize)

restored.frombytes(payload)
print("Loading again appends:", restored.tolist())

try:
    array("h").frombytes(b"\x00")
except ValueError:
    print("Rejected: incomplete item")

Run it:

python3 demo_array_buffer.py

Output:

Restored: [-100, 0, 100]
Equal: True
Payload size matches: True
Loading again appends: [-100, 0, 100, -100, 0, 100]
Rejected: incomplete item

"h" uses signed short storage. frombytes() appends to its target, so start with an empty array for a fresh copy. A buffer must contain whole items. These array operations use native machine representation; itemsize reports bytes per item.

This round-trip stays in one process. A raw payload carries no type code, item size, or byte-order metadata. For a portable binary file or network format, define that information explicitly, for example with struct. For readable interchange, consider CSV or JSON.

Choose an array deliberately

A list is convenient when values have mixed types. An array is worth considering for a homogeneous numeric buffer. Its + operator joins sequences and * repeats them; neither performs element-by-element arithmetic. Use a comprehension for a small transformation, or evaluate a numerical library when you need larger calculations.

Clean up

In the same Bash session, remove only the scripts and the empty working directory:

rm -- demo_array_samples.py demo_array_bounds.py demo_array_buffer.py
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect what remains rather than deleting it recursively.

References

Acknowledgements

This post was created with assistance from AI.

Last updated on