Parameter class utilities.
Project description
paramclass
paramclass is a small Python library for making imperative construction APIs
usable from declarative, class-body designs.
Many modeling libraries are built around imperative Python calls: create an
object, attach components, call helper functions, mutate state. That is
flexible, but it can make reusable model definitions harder to lint, statically
analyze, compare, and package. paramclass lets you keep those ordinary Python
calls while presenting the model definition as a compact class.
It lets you write dependencies once:
from paramclass import ParamClass
class Demo(ParamClass):
x = 2
y = x + 3
assert Demo().y == 5
assert Demo(x=10).y == 13
The goal is to make reusable object construction feel lightweight and inspectable: public class attributes become overrideable parameters, and expressions that reference those parameters are evaluated when an instance is built.
Project Timeline
paramclass was developed during 2023-2024 and has been used in production
workflows since 2023. Public packaging was added in 2025, and public
documentation was added in 2026 to make the project easier to evaluate, install,
and reuse outside its original environment.
Install
pip install paramclass
For local development:
uv sync --extra dev
uv run --extra dev pytest
Why
Python classes are a natural place to describe reusable structure. They give linters, type checkers, code search, review tools, and documentation generators a stable surface to inspect.
But normal class attributes are evaluated immediately. That makes dependent defaults hard to override cleanly:
class Normal:
x = 2
y = x + 3
normal = Normal()
normal.x = 10
assert normal.y == 5
ParamClass keeps the class-body syntax, but defers parameter expressions until
instance construction. That creates a bridge between two useful styles:
- declarative definitions that are easy to read, lint, review, and analyze
- imperative constructors and modeling APIs that already exist in the Python ecosystem
This is especially useful for libraries such as Pyomo or neural network modeling toolkits, where model pieces are often assembled through Python calls but teams still want code that can be scanned, checked, and reused consistently.
Examples
Literal Parameters
class Config(ParamClass):
width = 128
height = 64
size = width * height
assert Config().size == 8192
assert Config(width=256).size == 16384
Function Calls
def label(name, version):
return f"{name}:{version}"
class Job(ParamClass):
name = "trainer"
version = 1
tag = label(name, version)
assert Job().tag == "trainer:1"
assert Job(version=2).tag == "trainer:2"
Collections
Links can be nested inside lists, tuples, and dictionaries.
class Batch(ParamClass):
size = 32
settings = {
"train": [size, size * 2],
"eval": (size // 2),
}
assert Batch(size=64).settings == {
"train": [64, 128],
"eval": 32,
}
Nested ParamClasses
ParamClass instances can be nested and referenced by later parameters.
class Layer(ParamClass):
width = 128
params = width * 4
class Model(ParamClass):
layer = Layer()
total_params = layer.params + 10
assert Model().total_params == 522
assert Model(layer=Layer(width=256)).total_params == 1034
Methods Stay Methods
Normal methods, properties, static methods, and class methods are not treated as parameters.
class Counter(ParamClass):
value = 2
@property
def doubled(self):
return self.value * 2
assert Counter(value=5).doubled == 10
How It Works
ParamClass uses a custom class namespace while the class body is being
defined. Public assignments are captured as deferred parameter definitions.
References between parameters become links that are resolved during instance
construction, after any keyword overrides have been applied.
The result is a declarative class definition backed by ordinary Python execution at build time.
This means:
- public class-body assignments define instance parameters
- keyword arguments override those parameters
- dependent expressions are rebuilt from the final parameter values
- methods and descriptors remain normal class members
Current Limitations
Some Python language constructs cannot be deferred because they require an
immediate truth value during class creation. In particular, and, or, and
not are not traceable in the same way as arithmetic and comparison operators.
Use explicit comparisons or helper functions when you need deferred boolean logic.
Testing
uv run --extra dev pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paramclass-1.1.1.tar.gz.
File metadata
- Download URL: paramclass-1.1.1.tar.gz
- Upload date:
- Size: 10.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
690b3cc202c8490003d37b1d0d3b844bf27936920cbd0f818b556465fc12bd00
|
|
| MD5 |
491ca81f55d38d9a0e8238ed4e69059a
|
|
| BLAKE2b-256 |
f9340ad623c92b527e41a3ce75b8589cc6a2a53fa246cda46dc9009af9cc6d48
|
File details
Details for the file paramclass-1.1.1-py3-none-any.whl.
File metadata
- Download URL: paramclass-1.1.1-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b281227cd48bec122bc935d685620089351f572e599f51f06f89e3b5b286914
|
|
| MD5 |
7b71d9a7974be8bb2a4445ff01911e32
|
|
| BLAKE2b-256 |
93d8fcfdfaf348e0a6cc7265fa1c7b524323ce38080a9badd44bb27a7e086d36
|