6. Properties¶
6.1. Define computed properties with @pproperty.¶
from pconfigs import pconfig, pproperty
@pconfig
class LineConfig:
m: float # PConfigs are dataclasses that hold config.
b: float # All dataclass fields must be annotated.
@pproperty # @pproperty's are dataclass fields whose
def m(self) -> float: # value is computed at construction time.
return 2 * self.b
line_config = LineConfig(
m=1.0, # Input value will be replaced (see also ¶3 below).
b=1.0,
)
>>> print(line_config)
>>> LineConfig(
>>> m=2.0, # Line config contains the computed value of m.
>>> b=1.0,
>>> )
6.2. Modify user input values with @pinputs.¶
from pconfigs import pinputs, pdefaults
@pconfig
class VehicleConfig:
make: str
speed: float
@pproperty
def speed(self) -> float:
user_input_speed = pinputs(self).speed # Get property input value.
return max(0, user_input_speed)
pdefaults += VehicleConfig(
make="BMW",
speed=80,
)
vehicle_config = VehicleConfig(
speed=-1,
)
>>> print(vehicle_config)
>>> VehicleConfig(
>>> make="BMW",
>>> speed=0, # Computed property corrects the value.
>>> )
6.3. Prevent users from setting computed properties.¶
from pconfigs import Pinned
@pconfig
class FancyVehicleConfig(VehicleConfig):
speed: Pinned[float] # Input is not accepted. Mark as Pinned.
velocity: Tuple[float, float]
@pproperty
def speed(self) -> float:
return norm(self.velocity)
fancy_vehicle_config = FancyVehicleConfig(
speed=-1, # User cannot set a Pinned field.
velocity=(50, 50),
)
>>> ValueError: Cannot set a pinned field. Use FancyVehicleConfig.speed=Pinned
>>> to fix this error.
fancy_vehicle_config = FancyVehicleConfig(
speed=Pinned,
velocity=(50, 50),
)
>>> print(fancy_vehicle_config)
>>> FancyVehicleConfig(
>>> make="BMW",
>>> speed=70.71067811865476, # Pinned (omit from config)
>>> velocity=(50, 50),
>>> )