SerializableProperty#
- class jangada.serialization.SerializableProperty(postinitializer: Callable[[object], T] | None = None, default: T | Callable[[object], T] | None = None, parser: Callable[[object, Any], T] | None = None, observers: set[Callable[[object, T, T], None]] | None = None, writeonce: bool = False, copiable: bool = True, doc: str | None = None)#
Bases:
objectA descriptor for properties that support defaults, parsing, observation, and post-initialization hooks.
SerializableProperty provides a rich descriptor implementation designed for scientific computing applications where properties need validation, change tracking, lazy initialization, and eventual serialization to disk (e.g., HDF5).
- Parameters:
- postinitializerPostinitializer | None, optional
Function called once after the property is first set or accessed. Receives the instance as its only argument. Useful for lazy setup of related state or expensive initialization. Default is None.
- defaultT | DefaultCallable | None, optional
Default value for the property. Can be: - A static value (used directly) - A callable receiving the instance and returning the default - None (property defaults to None) Setting the property to None resets it to this default. Default is None.
- parserParser | None, optional
Function to parse/validate values before storage. Receives the instance and raw value, returns the parsed value. Applied to both explicitly set values and defaults. Exceptions raised by the parser propagate to the caller. Default is None.
- observersset[Observer] | None, optional
Set of functions called after the property value changes. Each observer receives (instance, old_value, new_value). Observers are called after parsing and storage, but before post-initialization. Default is None.
- writeoncebool, optional
If True, the property can only be set once (including initialization). Subsequent sets raise AttributeError. Useful for immutable configuration. Default is False.
- copiablebool, optional
Flag indicating whether this property should be included when copying or serializing instances. Used by serialization systems to determine which properties to persist. Default is True.
- docstr | None, optional
Documentation string for the property. Default is None.
- Attributes:
- namestr
Name of the property (set by __set_name__).
- ownertype
Class that owns this descriptor (set by __set_name__).
- private_namestr
Internal attribute name used to store the value on instances.
writeonceboolWhether this property can only be set once.
copiableboolWhether this property should be included in serialization.
See also
propertyPython’s built-in property descriptor
dataclasses.fieldSimilar concept for dataclasses
Notes
Properties are stored in instance.__dict__ with mangled names to avoid conflicts with user attributes.
Setting a property to None resets it to its default value.
Observers are called on first access (with old_value=None) when the property is initialized with its default.
Post-initializers run after the first set completes, allowing them to safely access the property value.
Parsers are applied to default values as well as explicitly set values.
All decorator methods (.default(), .parser(), etc.) return new descriptor instances rather than mutating the existing one.
Properties cannot be deleted (raises AttributeError).
Examples
Basic usage with static default:
>>> class Experiment: ... temperature = SerializableProperty(default=293.15) ... >>> exp = Experiment() >>> exp.temperature 293.15 >>> exp.temperature = 373.15 >>> exp.temperature 373.15
Using a callable default for mutable objects:
>>> class DataContainer: ... data = SerializableProperty(default=lambda self: []) ... >>> c1 = DataContainer() >>> c2 = DataContainer() >>> c1.data.append(1) >>> c2.data.append(2) >>> c1.data [1] >>> c2.data [2]
Using a parser for validation:
>>> class PositiveValue: ... value = SerializableProperty( ... default=1.0, ... parser=lambda self, v: max(0.0, float(v)) ... ) ... >>> obj = PositiveValue() >>> obj.value = -5 >>> obj.value 0.0
Using decorators for cleaner syntax:
>>> class System: ... data = SerializableProperty() ... ... @data.default ... def data(self): ... return {"initialized": True} ... ... @data.parser ... def data(self, value): ... if not isinstance(value, dict): ... raise TypeError("data must be a dict") ... return value ... ... @data.add_observer ... def data(self, old, new): ... print(f"Data changed from {old} to {new}")
Using post-initializer for lazy setup:
>>> class LazyLoader: ... data = SerializableProperty(default=None) ... ... @data.postinitializer ... def data(self): ... print("Loading expensive data...") ... if self.data is None: ... self.data = list(range(1000)) ... >>> loader = LazyLoader() >>> # No output yet - not accessed >>> _ = loader.data Loading expensive data... >>> len(loader.data) 1000
Write-once property for configuration:
>>> class Config: ... api_key = SerializableProperty(writeonce=True) ... >>> cfg = Config() >>> cfg.api_key = "secret123" >>> cfg.api_key = "different" # Raises AttributeError Traceback (most recent call last): ... AttributeError: api_key is a write-once property and has already been set
Type Aliases#
SerializableProperty uses type aliases to provide clear signatures for callback functions. See Type Aliases for detailed documentation.
T- Type variable for property valuesDefaultCallable- Default value factory signatureObserver- Change observer signatureParser- Value parser/validator signaturePostinitializer- Post-initializer signature
Descriptor Protocol#
The descriptor protocol methods that define how SerializableProperty integrates with Python’s attribute access mechanism.
|
Called when the descriptor is assigned to a class attribute. |
|
Get the property value from an instance. |
|
Set the property value on an instance. |
|
Prevent deletion of the property. |
Decorator Methods#
Methods for configuring property behavior using decorator syntax. These methods return new descriptor instances rather than modifying the existing one.
Set a post-initialization function using decorator syntax. |
|
Set a default value factory using decorator syntax. |
|
Set a parser/validator function using decorator syntax. |
|
Add an observer function using decorator syntax. |
|
Remove an observer function. |
Read-Only Properties#
Attributes that provide information about the descriptor’s configuration.
Whether this property can only be set once. |
|
Whether this property should be included in serialization. |