Python List vs NumPy Array Input Compatibility in pybind11-rdp: A Complete Guide
The pybind11-rdp library accepts both Python lists and NumPy arrays interchangeably by converting all inputs to NumPy ndarrays via np.asarray before passing them to the underlying C++ Eigen bindings.
The cubao/pybind11-rdp package implements the Ramer-Douglas-Peucker (RDP) algorithm with a high-performance C++ backend wrapped for Python. Understanding Python list vs NumPy array input compatibility is essential for writing flexible, efficient coordinate simplification code. The library seamlessly handles both input types through a thin Python wrapper that normalizes data before it reaches the C++ layer.
How the Python Wrapper Normalizes Input Types
The compatibility layer resides in src/pybind11_rdp/__init__.py, where the public API functions rdp(), rdp_rec(), and rdp_iter() preprocess all inputs. Each function calls np.asarray() to convert user-provided sequences into contiguous double-precision arrays before invoking the C++ bindings.
Specifically:
- Lines 36-39 handle conversion for
rdp_rec() - Lines 60-64 handle conversion for
rdp_iter() - Lines 89-94 handle conversion for the unified
rdp()entry point
This design means any array-like object—including native Python lists, tuples, or nested sequences—automatically becomes a NumPy ndarray with dtype=np.float64. The wrapper reshapes the data into the required (N, 2) or (N, 3) matrix format expected by the C++ implementation.
The C++ Eigen Interface
On the C++ side in src/main.cpp, the bindings receive data as Eigen matrix references rather than raw Python objects. The implementation defines two overloads:
- Lines 15-23 accept 3-column matrices (
Eigen::Ref<const RowVectors>) - Lines 25-33 accept 2-column matrices (
Eigen::Ref<const RowVectorsNx2>)
Because the Python wrapper always passes a NumPy ndarray, the C++ layer sees a contiguous block of memory compatible with Eigen's Map semantics. This zero-copy mapping ensures high performance regardless of whether the original input was a Python list or a NumPy array.
Supported Input Types and Conversion Behavior
The following table details how different input types are processed before reaching the C++ algorithm:
| Input Type | Python Wrapper Action | C++ Receives |
|---|---|---|
| Python list of lists/tuples | np.asarray builds float64 array, preserving nesting order |
Eigen::Ref<const RowVectors> (or RowVectorsNx2) referencing contiguous data |
NumPy ndarray |
np.asarray returns original object unchanged |
Same Eigen reference type as above |
| Other array-like objects (e.g., pandas DataFrame values) | np.asarray attempts conversion; succeeds if result is 2-D float array |
Same as above (requires shape (N,2) or (N,3)) |
If the supplied data cannot be cast to a 2-D float64 array—for example, if inner lists have mismatched lengths—NumPy raises a ValueError before the C++ layer executes.
Practical Code Examples
The following examples demonstrate Python list vs NumPy array input compatibility using the rdp() function:
import numpy as np
from pybind11_rdp import rdp
# Example 1 – plain Python list (2-D points)
points_list = [[0, 0], [1, 0.1], [2, -0.1], [3, 5]]
simplified = rdp(points_list, epsilon=0.5)
print("simplified (list input):", simplified)
# Example 2 – NumPy ndarray (3-D points)
points_array = np.array([[0, 0, 0],
[1, 0.1, 0],
[2, -0.1, 0],
[3, 5, 0]], dtype=np.float64)
simplified = rdp(points_array, epsilon=0.5, algo="rec")
print("simplified (ndarray input):", simplified)
# Example 3 – request the keep-mask instead of coordinates
mask = rdp(points_list, epsilon=0.5, return_mask=True)
print("mask:", mask)
All three calls succeed because the wrapper transparently converts inputs to NumPy arrays before invoking the C++ implementation.
Error Handling and Validation
When working with heterogeneous input data, the library relies on NumPy's strict casting rules. Malformed inputs—such as jagged lists or non-numeric sequences—trigger a ValueError during the np.asarray() call in the Python wrapper. This prevents undefined behavior in the C++ layer and provides clear error messages at the Python level.
The wrapper requires inputs to resolve to either:
- Shape
(N, 2)for 2-D coordinate simplification - Shape
(N, 3)for 3-D coordinate simplification
Any other dimensionality raises a standard NumPy reshape error before reaching the Eigen bindings in src/main.cpp.
Summary
- Universal Input Support: The
pybind11_rdpAPI accepts Python lists, tuples, and NumPy arrays through automaticnp.asarrayconversion insrc/pybind11_rdp/__init__.py. - Zero-Copy Performance: C++ bindings use
Eigen::Refto map NumPy memory directly without copying, ensuring high performance regardless of input type. - Strict Validation: Input arrays must convert to 2-D
float64with shape(N,2)or(N,3); otherwise, NumPy raisesValueErrorbefore C++ execution. - Implementation Files: Key logic resides in
src/pybind11_rdp/__init__.py(Python wrapper) andsrc/main.cpp(C++ Eigen bindings).
Frequently Asked Questions
Does pybind11-rdp accept Python lists or only NumPy arrays?
Both input types are fully supported. The library uses np.asarray() in the Python wrapper to convert lists, tuples, and other sequences into NumPy ndarrays before passing them to the C++ implementation. This conversion happens automatically in the rdp(), rdp_rec(), and rdp_iter() functions.
What data types does pybind11-rdp expect for coordinate inputs?
The wrapper forces dtype=np.float64 (double precision). While the input can be any array-like object, the np.asarray() call without explicit dtype specification creates a float64 array by default when given Python floats. The C++ Eigen bindings expect this specific memory layout for optimal performance.
How does the library handle pandas DataFrame inputs?
Pandas DataFrames work if converted to 2-D array values first. Passing df.values or any attribute that yields a 2-D array-like structure allows np.asarray to create the required matrix. The wrapper treats these objects identically to standard NumPy arrays once converted.
What happens if I pass a malformed list to the rdp function?
NumPy raises a ValueError before the C++ code executes. If inner lists have inconsistent lengths or contain non-numeric data, the np.asarray() call in src/pybind11_rdp/__init__.py fails with a descriptive error message. This prevents crashes in the underlying C++ RDP algorithm.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →