%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%0A%23%20%20%20%20%20%22numpy%22%2C%0A%23%20%20%20%20%20%22scikit-learn%22%2C%0A%23%20%20%20%20%20%22sklearn-wrap%22%2C%0A%23%20%5D%0A%23%20%2F%2F%2F%0A%22%22%22%0A%23%20How%20to%20Validate%20Parameters%20and%20Handle%20Errors%0A%0ACatch%20invalid%20parameters%2C%20enforce%20base%20class%20requirements%2C%20and%20define%20parameter%0Aconstraints%20on%20wrapped%20estimators.%0A%22%22%22%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.2%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20from%20sklearn.base%20import%20BaseEstimator%0A%0A%20%20%20%20from%20sklearn_wrap%20import%20BaseClassWrapper%0A%0A%20%20%20%20return%20BaseClassWrapper%2C%20BaseEstimator%2C%20np%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20This%20guide%20covers%20five%20common%20error%20patterns%20and%20the%20mechanisms%20that%20catch%0A%20%20%20%20them%3A%20constructor%20validation%2C%20base%20class%20enforcement%2C%20and%20parameter%20constraints.%0A%0A%20%20%20%20**Prerequisites**%20-%20Familiarity%20with%20%5Bfirst_wrapper.py%5D(first_wrapper.py).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%201.%20Invalid%20Parameters%0A%0A%20%20%20%20Pass%20a%20parameter%20that%20does%20not%20exist%20in%20the%20wrapped%20class's%20constructor.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.class_definition%0Aclass%20SimpleModel%3A%0A%20%20%20%20%22%22%22Simple%20model%20without%20sklearn%20conventions.%22%22%22%0A%0A%20%20%20%20def%20__init__(self%2C%20valid_param%3D1.0)%3A%0A%20%20%20%20%20%20%20%20self._internal_param%20%3D%20valid_param%0A%0A%0A%40app.cell%0Adef%20_(BaseClassWrapper)%3A%0A%20%20%20%20class%20SimpleWrapper(BaseClassWrapper)%3A%0A%20%20%20%20%20%20%20%20_estimator_name%20%3D%20%22model%22%0A%20%20%20%20%20%20%20%20_estimator_base_class%20%3D%20object%0A%0A%20%20%20%20%20%20%20%20def%20fit(self%2C%20X%2C%20y)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.instantiate()%0A%20%20%20%20%20%20%20%20%20%20%20%20self.fitted_%20%3D%20True%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self%0A%0A%20%20%20%20return%20(SimpleWrapper%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20def%20create_error_demo(operation%2C%20error_title%2C%20explanation)%3A%0A%20%20%20%20%20%20%20%20error_msg%20%3D%20None%0A%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20operation()%0A%20%20%20%20%20%20%20%20except%20(ValueError%2C%20TypeError)%20as%20e%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20error_msg%20%3D%20str(e)%0A%20%20%20%20%20%20%20%20def%20display()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20error_msg%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20mo.md(f%22%23%23%23%20%7Berror_title%7D%5Cn%5Cn%60%60%60%5Cn%7Berror_msg%7D%5Cn%60%60%60%5Cn%5Cn%7Bexplanation%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20mo.md(%22No%20error%20was%20raised%20(unexpected)%22)%0A%20%20%20%20%20%20%20%20return%20display%0A%0A%20%20%20%20return%20(create_error_demo%2C)%0A%0A%0A%40app.cell%0Adef%20_(SimpleWrapper)%3A%0A%20%20%20%20def%20invalid_param_operation()%3A%0A%20%20%20%20%20%20%20%20wrapper%20%3D%20SimpleWrapper(model%3DSimpleModel%2C%20valid_param%3D1.0)%0A%20%20%20%20%20%20%20%20wrapper.set_params(nonexistent_param%3D999)%0A%0A%20%20%20%20return%20(invalid_param_operation%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(create_error_demo%2C%20invalid_param_operation)%3A%0A%20%20%20%20_display%20%3D%20create_error_demo(%0A%20%20%20%20%20%20%20%20invalid_param_operation%2C%0A%20%20%20%20%20%20%20%20%22Invalid%20Parameter%22%2C%0A%20%20%20%20%20%20%20%20%22Only%20parameters%20defined%20in%20%60SimpleModel.__init__%60%20are%20allowed.%22%2C%0A%20%20%20%20)%0A%20%20%20%20_display()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%202.%20Wrong%20Base%20Class%0A%0A%20%20%20%20Set%20%60_estimator_base_class%60%20to%20enforce%20inheritance%20requirements.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(BaseClassWrapper%2C%20BaseEstimator)%3A%0A%20%20%20%20class%20StrictWrapper(BaseClassWrapper)%3A%0A%20%20%20%20%20%20%20%20_estimator_name%20%3D%20%22estimator%22%0A%20%20%20%20%20%20%20%20_estimator_base_class%20%3D%20BaseEstimator%20%20%23%20Requires%20sklearn's%20BaseEstimator%0A%0A%20%20%20%20return%20(StrictWrapper%2C)%0A%0A%0A%40app.class_definition%0Aclass%20NotSklearnClass%3A%0A%20%20%20%20def%20__init__(self)%3A%0A%20%20%20%20%20%20%20%20pass%0A%0A%0A%40app.cell%0Adef%20_(StrictWrapper)%3A%0A%20%20%20%20def%20wrong_base_operation()%3A%0A%20%20%20%20%20%20%20%20StrictWrapper(estimator%3DNotSklearnClass)%0A%0A%20%20%20%20return%20(wrong_base_operation%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(create_error_demo%2C%20wrong_base_operation)%3A%0A%20%20%20%20_display%20%3D%20create_error_demo(%0A%20%20%20%20%20%20%20%20wrong_base_operation%2C%0A%20%20%20%20%20%20%20%20%22Base%20Class%20Validation%22%2C%0A%20%20%20%20%20%20%20%20%22%60NotSklearnClass%60%20doesn't%20inherit%20from%20%60sklearn.base.BaseEstimator%60.%22%2C%0A%20%20%20%20)%0A%20%20%20%20_display()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%203.%20Missing%20Required%20Parameters%0A%0A%20%20%20%20Parameters%20without%20defaults%20must%20be%20provided%20during%20instantiation.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.class_definition%0Aclass%20ModelWithRequired%3A%0A%20%20%20%20def%20__init__(self%2C%20required_param%2C%20optional_param%3D10)%3A%0A%20%20%20%20%20%20%20%20self.required_param%20%3D%20required_param%0A%20%20%20%20%20%20%20%20self.optional_param%20%3D%20optional_param%0A%0A%0A%40app.cell%0Adef%20_(SimpleWrapper%2C%20np)%3A%0A%20%20%20%20def%20missing_required_operation()%3A%0A%20%20%20%20%20%20%20%20%23%20Create%20wrapper%20without%20required_param%0A%20%20%20%20%20%20%20%20wrapper%20%3D%20SimpleWrapper(model%3DModelWithRequired%2C%20optional_param%3D20)%0A%20%20%20%20%20%20%20%20%23%20Error%20happens%20during%20instantiate()%0A%20%20%20%20%20%20%20%20wrapper.fit(np.array(%5B%5B1%2C%202%5D%5D)%2C%20np.array(%5B1%5D))%0A%0A%20%20%20%20return%20(missing_required_operation%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(create_error_demo%2C%20missing_required_operation)%3A%0A%20%20%20%20_display%20%3D%20create_error_demo(%0A%20%20%20%20%20%20%20%20missing_required_operation%2C%0A%20%20%20%20%20%20%20%20%22Missing%20Required%20Parameter%22%2C%0A%20%20%20%20%20%20%20%20%22%60required_param%60%20has%20no%20default%20value%20and%20must%20be%20explicitly%20provided.%22%2C%0A%20%20%20%20)%0A%20%20%20%20_display()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%204.%20Double%20Underscore%20Reserved%0A%0A%20%20%20%20The%20%60__%60%20delimiter%20is%20reserved%20for%20nested%20parameter%20syntax.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(SimpleWrapper)%3A%0A%20%20%20%20def%20reserved_delimiter_operation()%3A%0A%20%20%20%20%20%20%20%20SimpleWrapper(model%3DSimpleModel%2C%20param__invalid%3D1.0)%0A%0A%20%20%20%20return%20(reserved_delimiter_operation%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(create_error_demo%2C%20reserved_delimiter_operation)%3A%0A%20%20%20%20_display%20%3D%20create_error_demo(%0A%20%20%20%20%20%20%20%20reserved_delimiter_operation%2C%0A%20%20%20%20%20%20%20%20%22Reserved%20Delimiter%22%2C%0A%20%20%20%20%20%20%20%20%22Parameter%20names%20cannot%20contain%20%60__%60%20-%20it's%20reserved%20for%20nested%20params%20like%20%60model__alpha%60.%22%2C%0A%20%20%20%20)%0A%20%20%20%20_display()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%205.%20Parameter%20Constraints%0A%0A%20%20%20%20Define%20%60_parameter_constraints%60%20to%20enforce%20type%20and%20inheritance%20requirements%0A%20%20%20%20on%20wrapper%20parameters.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(np)%3A%0A%20%20%20%20class%20SimpleRegressor%3A%0A%20%20%20%20%20%20%20%20%22%22%22Non-sklearn%20regressor%20for%20validation%20examples.%22%22%22%0A%0A%20%20%20%20%20%20%20%20def%20__init__(self%2C%20scale%3D1.0)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self._scale_param%20%3D%20scale%0A%0A%20%20%20%20%20%20%20%20def%20train_model(self%2C%20X%2C%20y)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Train%20the%20model%20(not%20'fit').%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20self._computed_mean%20%3D%20y.mean()%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self%0A%0A%20%20%20%20%20%20%20%20def%20compute_output(self%2C%20X)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Compute%20output%20(not%20'predict').%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20np.full(X.shape%5B0%5D%2C%20self._computed_mean%20*%20self._scale_param)%0A%0A%20%20%20%20return%20(SimpleRegressor%2C)%0A%0A%0A%40app.class_definition%0Aclass%20EnsembleModel%3A%0A%20%20%20%20%22%22%22Ensemble%20model%20without%20sklearn%20conventions.%22%22%22%0A%0A%20%20%20%20def%20__init__(self%2C%20inner_estimator)%3A%0A%20%20%20%20%20%20%20%20self._wrapped_estimator%20%3D%20inner_estimator%0A%0A%20%20%20%20def%20train_ensemble(self%2C%20X%2C%20y)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Train%20the%20ensemble%20(not%20'fit').%22%22%22%0A%20%20%20%20%20%20%20%20self._wrapped_estimator.fit(X%2C%20y)%0A%20%20%20%20%20%20%20%20return%20self%0A%0A%20%20%20%20def%20generate_output(self%2C%20X)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Generate%20output%20(not%20'predict').%22%22%22%0A%20%20%20%20%20%20%20%20return%20self._wrapped_estimator.predict(X)%0A%0A%0A%40app.cell%0Adef%20_(BaseClassWrapper)%3A%0A%20%20%20%20class%20RegressorWrapper(BaseClassWrapper)%3A%0A%20%20%20%20%20%20%20%20_estimator_name%20%3D%20%22regressor%22%0A%20%20%20%20%20%20%20%20_estimator_base_class%20%3D%20object%0A%0A%20%20%20%20%20%20%20%20def%20fit(self%2C%20X%2C%20y)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.instantiate()%0A%20%20%20%20%20%20%20%20%20%20%20%20self.instance_.train_model(X%2C%20y)%0A%20%20%20%20%20%20%20%20%20%20%20%20self.fitted_%20%3D%20True%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self%0A%0A%20%20%20%20%20%20%20%20def%20predict(self%2C%20X)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self.instance_.compute_output(X)%0A%0A%20%20%20%20return%20(RegressorWrapper%2C)%0A%0A%0A%40app.cell%0Adef%20_(BaseClassWrapper)%3A%0A%20%20%20%20class%20EnsembleWrapper(BaseClassWrapper)%3A%0A%20%20%20%20%20%20%20%20_estimator_name%20%3D%20%22ensemble%22%0A%20%20%20%20%20%20%20%20_estimator_base_class%20%3D%20object%0A%20%20%20%20%20%20%20%20_parameter_constraints%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22inner_estimator%22%3A%20%5B%7B%22wrapper_base_class%22%3A%20object%7D%5D%2C%20%20%23%20Wrapped%20estimator%20can%20be%20any%20class%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20def%20fit(self%2C%20X%2C%20y)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.instantiate()%0A%20%20%20%20%20%20%20%20%20%20%20%20self.instance_.train_ensemble(X%2C%20y)%0A%20%20%20%20%20%20%20%20%20%20%20%20self.fitted_%20%3D%20True%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self%0A%0A%20%20%20%20%20%20%20%20def%20predict(self%2C%20X)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self.instance_.generate_output(X)%0A%0A%20%20%20%20return%20(EnsembleWrapper%2C)%0A%0A%0A%40app.cell%0Adef%20_(EnsembleWrapper%2C%20SimpleRegressor)%3A%0A%20%20%20%20def%20non_wrapper_constraint_operation()%3A%0A%20%20%20%20%20%20%20%20%23%20This%20fails%3A%20SimpleRegressor%20is%20not%20a%20BaseClassWrapper%0A%20%20%20%20%20%20%20%20raw_estimator%20%3D%20SimpleRegressor(scale%3D1.0)%0A%20%20%20%20%20%20%20%20EnsembleWrapper(ensemble%3DEnsembleModel%2C%20inner_estimator%3Draw_estimator)%0A%0A%20%20%20%20return%20(non_wrapper_constraint_operation%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(create_error_demo%2C%20non_wrapper_constraint_operation)%3A%0A%20%20%20%20_display%20%3D%20create_error_demo(%0A%20%20%20%20%20%20%20%20non_wrapper_constraint_operation%2C%0A%20%20%20%20%20%20%20%20%22Type%20Constraint%20Violation%22%2C%0A%20%20%20%20%20%20%20%20%22%60inner_estimator%60%20must%20be%20a%20BaseClassWrapper%20instance%20per%20%60_parameter_constraints%60.%22%2C%0A%20%20%20%20)%0A%20%20%20%20_display()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Valid%20Constrained%20Usage%0A%0A%20%20%20%20Provide%20a%20%60BaseClassWrapper%60%20instance%20to%20satisfy%20the%20constraint.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(EnsembleWrapper%2C%20RegressorWrapper%2C%20SimpleRegressor%2C%20np)%3A%0A%20%20%20%20%23%20This%20works%3A%20inner_estimator%20is%20a%20BaseClassWrapper%0A%20%20%20%20inner_wrapper%20%3D%20RegressorWrapper(regressor%3DSimpleRegressor%2C%20scale%3D1.5)%0A%20%20%20%20valid_ensemble%20%3D%20EnsembleWrapper(ensemble%3DEnsembleModel%2C%20inner_estimator%3Dinner_wrapper)%0A%0A%20%20%20%20%23%20Test%20it%0A%20%20%20%20X_ensemble%20%3D%20np.array(%5B%5B1%5D%2C%20%5B2%5D%2C%20%5B3%5D%5D)%0A%20%20%20%20y_ensemble%20%3D%20np.array(%5B10%2C%2020%2C%2030%5D)%0A%20%20%20%20valid_ensemble.fit(X_ensemble%2C%20y_ensemble)%0A%20%20%20%20ensemble_predictions%20%3D%20valid_ensemble.predict(X_ensemble)%0A%20%20%20%20return%20(ensemble_predictions%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(ensemble_predictions%2C%20mo)%3A%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20Valid%20ensemble%20created%20and%20fitted%20successfully%0A%0A%20%20%20%20**Predictions%3A**%20%7Bensemble_predictions%7D%0A%0A%20%20%20%20Constraints%20ensure%20type%20safety%20and%20proper%20composition%20patterns.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20**More%20examples%3A**%20%5Bparameter_interface.py%5D(parameter_interface.py)%20%7C%20%5Bnested_wrappers.py%5D(nested_wrappers.py)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
cd77fccfe22eee37c5cdb23adf439df4