A training script and a statistics module both have numeric settings that must stay within bounds: a learning rate between 0 and 1, a whole number of epochs of at least 1, a positive shape parameter. Writing a property for each would repeat the same checks many times. Write a class Bounded whose instances, placed on a class, check an attribute every time it is assigned:
class Trainer:
learning_rate = Bounded(0, 1)
epochs = Bounded(1, None, integer=True)
Bounded(low, high, integer=False):
- An assigned value must be an
intor afloatbut not abool, otherwiseTypeError. Withinteger=Trueit must be anint(and not abool), otherwiseTypeError. - It must satisfy
low <= value <= high, where a bound ofNonemeans no limit on that side, otherwiseValueError. - The message of each error starts with the attribute's name, for example
"epochs must be at least 1, got 0". - A rejected assignment leaves the previous value in place. Each instance has its own value; reading an attribute that was never assigned raises
AttributeError. - Reading the attribute on the class itself (
Trainer.epochs) returns theBoundedobject, which has the attributesname,lowandhigh.
The tests build classes that use your Bounded inside setup helpers you can call with Run: trainer_class(), beta_class(), configure(rows), change_later(), two_trainers(), on_the_class(), not_set_yet() and shapes(pairs). outcome(call) returns a result, or the exception's name and the first word of its message.
Examples
Input: configure([(0.1, 20), (0.1, 0), (1.5, 3), (0.2, 5, True), ("0.1", 5)])
Output: [(0.1, 20, 32), ("ValueError", "epochs"), ("ValueError", "learning_rate"), ("TypeError", "batch_size"), ("TypeError", "learning_rate")]
Input: on_the_class()
Output: ("Bounded", "epochs", 1, None, "batch_size", "alpha", 0.001)
Constraints
- Bounds are numbers or
None; values are checked in the order the class assigns them.
Goals
- Write a data descriptor with `__get__`, `__set__` and `__set_name__`
- Store each instance's value on the instance, under a name that does not clash with the descriptor
- Reuse one validation rule for many attributes of several classes