.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/recipies/_03_composite_objects.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_recipies__03_composite_objects.py: .. _compositeobjects: Composite-Algorithms and Pipelines ================================== Sometimes a pipeline or algorithms requires a list of parameters or nested objects. As we can not support parameters which names are not known when the class is defined, such cases need to be handled via composite fields. A composite field is a parameter expecting a value of the shape `[(name1, sub_para1), (name2, sub_para2), ...]`. The sub-paras can themselves be tpcp objects. As it is difficult at runtime to know, if a parameter is expected to be a composite field, you need to actively specify all fields that should be considered composite fields during class definition using the `_composite_params` attribute: .. GENERATED FROM PYTHON SOURCE LINES 18-36 .. code-block:: default import dataclasses import traceback from typing import Optional from tpcp import Pipeline from tpcp.exceptions import ValidationError @dataclasses.dataclass class Workflow(Pipeline): _composite_params = ("pipelines",) pipelines: Optional[list[tuple[str, Pipeline]]] = None def __init__(self, pipelines=None): self.pipelines = pipelines .. GENERATED FROM PYTHON SOURCE LINES 37-41 That's it! Now tpcp knows, that `pipelines` should be a composite field and will actually complain, if we try to assign something invalid. Composite fields are allowed to either have the value None, or be a list of tuples as explained above .. GENERATED FROM PYTHON SOURCE LINES 41-44 .. code-block:: default instance = Workflow() instance.pipelines # Our default value of None .. GENERATED FROM PYTHON SOURCE LINES 45-52 .. code-block:: default instance.pipelines = "something invalid" try: print(instance.get_params()) except ValidationError: traceback.print_exc() .. rst-class:: sphx-glr-script-out .. code-block:: none Traceback (most recent call last): File "/home/docs/checkouts/readthedocs.org/user_builds/tpcp/checkouts/latest/examples/recipies/_03_composite_objects.py", line 47, in print(instance.get_params()) File "/home/docs/checkouts/readthedocs.org/user_builds/tpcp/checkouts/latest/tpcp/_base.py", line 370, in get_params return _get_params(self, deep) File "/home/docs/checkouts/readthedocs.org/user_builds/tpcp/checkouts/latest/tpcp/_base.py", line 500, in _get_params _assert_is_allowed_composite_value(v, key, i) File "/home/docs/checkouts/readthedocs.org/user_builds/tpcp/checkouts/latest/tpcp/_base.py", line 456, in _assert_is_allowed_composite_value raise ValidationError( tpcp.exceptions.ValidationError: The provided parameters for the composite field pipelines does not seem to be the right type. It should be a sequence of `(name, value)` tuples, but the obj at position 0 in the sequence was not a tuple but: `s` .. GENERATED FROM PYTHON SOURCE LINES 53-55 While you could set the individual sub-params in a composite field to whatever you want, the real value of explicit composite fields are the use of tpcp-objects .. GENERATED FROM PYTHON SOURCE LINES 55-62 .. code-block:: default @dataclasses.dataclass class MyPipeline(Pipeline): param: float = 4 param2: int = 10 workflow_instance = Workflow(pipelines=[("pipe1", MyPipeline()), ("pipe2", MyPipeline(param2=5))]) .. GENERATED FROM PYTHON SOURCE LINES 63-64 We can now use `get_params` to get a deep inspection of the nested objects: .. GENERATED FROM PYTHON SOURCE LINES 64-66 .. code-block:: default workflow_instance.get_params(deep=True) .. rst-class:: sphx-glr-script-out .. code-block:: none {'pipelines__pipe1': MyPipeline(param=4, param2=10), 'pipelines__pipe1__param': 4, 'pipelines__pipe1__param2': 10, 'pipelines__pipe2': MyPipeline(param=4, param2=5), 'pipelines__pipe2__param': 4, 'pipelines__pipe2__param2': 5, 'pipelines': [('pipe1', MyPipeline(param=4, param2=10)), ('pipe2', MyPipeline(param=4, param2=5))]} .. GENERATED FROM PYTHON SOURCE LINES 67-68 Or we can set params using the following syntax: .. GENERATED FROM PYTHON SOURCE LINES 68-71 .. code-block:: default workflow_instance = workflow_instance.set_params(pipelines__pipe1__param=2, pipelines__pipe2=MyPipeline(param2=4)) workflow_instance.get_params(deep=True) .. rst-class:: sphx-glr-script-out .. code-block:: none {'pipelines__pipe1': MyPipeline(param=2, param2=10), 'pipelines__pipe1__param': 2, 'pipelines__pipe1__param2': 10, 'pipelines__pipe2': MyPipeline(param=4, param2=4), 'pipelines__pipe2__param': 4, 'pipelines__pipe2__param2': 4, 'pipelines': [('pipe1', MyPipeline(param=2, param2=10)), ('pipe2', MyPipeline(param=4, param2=4))]} .. GENERATED FROM PYTHON SOURCE LINES 72-74 Note that it is not possible to set parameters for keys that don't exist yet! In such a case, you would manually recreate the full list. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.364 seconds) **Estimated memory usage:** 9 MB .. _sphx_glr_download_auto_examples_recipies__03_composite_objects.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: _03_composite_objects.py <_03_composite_objects.py>` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: _03_composite_objects.ipynb <_03_composite_objects.ipynb>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_