Skip to main content

A lightweight wrapper around numexpr that adds support for registered callables and automatic type normalization

Project description

funcexpr

A lightweight wrapper around numexpr that adds support for registered callables and automatic type normalization.

import numpy as np
import funcexpr as fe

a = np.array([1.0, 2.0, 3.0])
b = np.array([4.0, 5.0, 6.0])

def clip_positive(x):
    return np.clip(x, 0, None)

result = fe.evaluate("clip_positive(a - b) + b", ctx={"a": a, "b": b}, funcs={"clip_positive": clip_positive})
# array([4., 5., 6.])

Motivation

numexpr is fast, but it only accepts plain ndarrays and supports a limited set of built-in functions. funcexpr solves this by pre-processing the expression AST before handing it off to numexpr:

  • Registered callables are evaluated eagerly via NumPy and replaced with temporary variables before the expression reaches numexpr
  • numexpr built-ins (sin, cos, exp, etc.) at the top level of an expression are passed through to numexpr as-is; when they appear as arguments to a registered callable, they are resolved via NumPy during eager argument evaluation
  • Type normalization handles Python scalars, numpy scalars, and any object implementing __array__

Installation

pip install funcexpr

Usage

Basic

import numpy as np
import funcexpr as fe

a = np.array([1.0, 2.0, 3.0])
b = np.array([4.0, 5.0, 6.0])

fe.evaluate("a + b * 2", ctx={"a": a, "b": b})
# array([ 9., 12., 15.])

Registered callables

Any Python callable can be registered via funcs. Arguments are evaluated eagerly before the callable is invoked, so nested calls and expressions as arguments work naturally.

def double(x):
    return x * 2

fe.evaluate("double(a) + b", ctx={"a": a, "b": b}, funcs={"double": double})
# array([ 6.,  9., 12.])

Nested calls:

fe.evaluate("double(double(a))", ctx={"a": a}, funcs={"double": double})
# array([ 4.,  8., 12.])

Expression as argument:

fe.evaluate("double(a + b)", ctx={"a": a, "b": b}, funcs={"double": double})
# array([10., 14., 18.])

numexpr built-ins

numexpr built-ins used at the top level of an expression are passed through to numexpr directly and require no registration.

fe.evaluate("sin(a) + cos(b)", ctx={"a": a, "b": b})

When a built-in appears as an argument to a registered callable, it is resolved via NumPy during eager argument evaluation.

def my_func(x):
    return x * 2

fe.evaluate("my_func(sin(a))", ctx={"a": a}, funcs={"my_func": my_func})
# equivalent to my_func(np.sin(a))

Type normalization

ctx values and callable return values are normalized automatically.

Type Behavior
int, float, complex passed through as-is
np.generic (numpy scalar) passed through as-is
np.ndarray passed through as-is
object with __array__ converted via np.asarray()
anything else TypeError

API reference

def evaluate(
    expr: str,
    ctx: dict[str, np.ndarray | int | float | complex | np.generic],
    funcs: dict[str, Callable] | None = None,
) -> np.ndarray:
Parameter Type Default Description
expr str Python expression string to evaluate
ctx dict Variable context
funcs dict[str, Callable] | None None Registered callables

Returns np.ndarray.

Error handling

Condition Exception
Invalid expression SyntaxError
Variable missing from ctx KeyError (raised by numexpr)
Unnormalizable type in ctx or callable return value TypeError
Unrecognized function name TypeError (raised by numexpr)
Any other numexpr or callable error propagated as-is

Limitations

Callable arguments support a subset of AST node types: Constant, Name, BinOp, UnaryOp, and Call. Passing unsupported node types (e.g. Compare, BoolOp, IfExp) as callable arguments will raise TypeError. This may be lifted in a future version.

Design

funcexpr is intentionally minimal. It does one thing: let you use arbitrary callables inside numexpr expressions. More advanced features such as xarray DataArray support and axis alignment are out of scope and belong in a higher-level layer.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

funcexpr-0.1.2.tar.gz (8.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

funcexpr-0.1.2-py3-none-any.whl (8.2 kB view details)

Uploaded Python 3

File details

Details for the file funcexpr-0.1.2.tar.gz.

File metadata

  • Download URL: funcexpr-0.1.2.tar.gz
  • Upload date:
  • Size: 8.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for funcexpr-0.1.2.tar.gz
Algorithm Hash digest
SHA256 4e81192773ff34d33a3f1dbae044c299f2a200e4630111e15fae1636f8dece88
MD5 9d70a3dbe66aee6f2b70c55b3eb4909a
BLAKE2b-256 275192c5f62c48143b35f0e974f5c600112f962359768881f52cda1ebf99252a

See more details on using hashes here.

File details

Details for the file funcexpr-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: funcexpr-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 8.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for funcexpr-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0937fcc18cedd8407f29f3a1cb6c50524ace843c3f47f5c0a3c39aaf0c5b588a
MD5 721bf863cee9b7b006588b0cea8eae6e
BLAKE2b-256 65167c537860d7482a9b7e91e8c733813969e3cbca4d0013d799ef27e77005cd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page