.. Comment: this file is automatically generated by `update_example_docs.py`. It should not be modified manually. .. _example-category-generics: Generics ======== :mod:`tyro`'s understanding of Python's type system includes user-defined parameterized types, which can reduce boilerplate and improve type safety. .. _example-01_generics_py312: Generics (3.12+) ---------------- This example uses syntax introduced in Python 3.12 (`PEP 695 `_). .. note:: If used in conjunction with :code:`from __future__ import annotations`, the updated type parameter syntax requires Python 3.12.4 or newer. For technical details, see `this CPython PR `_. .. code-block:: python :linenos: # 01_generics_py312.py import dataclasses import tyro @dataclasses.dataclass class Point3[ScalarType: (int, float)]: x: ScalarType y: ScalarType z: ScalarType frame_id: str @dataclasses.dataclass class Triangle: a: Point3[float] b: Point3[float] c: Point3[float] @dataclasses.dataclass class Args[ShapeType]: shape: ShapeType if __name__ == "__main__": args = tyro.cli(Args[Triangle]) print(args) .. raw:: html
    $ python ./01_generics_py312.py --help
    usage: ./01_generics_py312.py [-h] [OPTIONS]
    
     options ───────────────────────────────────────────────╮
     -h, --help              show this help message and exit 
    ─────────────────────────────────────────────────────────
     shape.a options ───────────────────────────────────────╮
     --shape.a.x FLOAT       (required)                      
     --shape.a.y FLOAT       (required)                      
     --shape.a.z FLOAT       (required)                      
     --shape.a.frame-id STR  (required)                      
    ─────────────────────────────────────────────────────────
     shape.b options ───────────────────────────────────────╮
     --shape.b.x FLOAT       (required)                      
     --shape.b.y FLOAT       (required)                      
     --shape.b.z FLOAT       (required)                      
     --shape.b.frame-id STR  (required)                      
    ─────────────────────────────────────────────────────────
     shape.c options ───────────────────────────────────────╮
     --shape.c.x FLOAT       (required)                      
     --shape.c.y FLOAT       (required)                      
     --shape.c.z FLOAT       (required)                      
     --shape.c.frame-id STR  (required)                      
    ─────────────────────────────────────────────────────────
    
.. _example-02_generics: Generics (Python <3.12) ----------------------- The legacy :py:class:`typing.Generic` and :py:class:`typing.TypeVar` syntax for generic types is also supported. .. code-block:: python :linenos: # 02_generics.py import dataclasses from typing import Generic, TypeVar import tyro ScalarType = TypeVar("ScalarType", int, float) ShapeType = TypeVar("ShapeType") @dataclasses.dataclass class Point3(Generic[ScalarType]): x: ScalarType y: ScalarType z: ScalarType frame_id: str @dataclasses.dataclass class Triangle: a: Point3[float] b: Point3[float] c: Point3[float] @dataclasses.dataclass class Args(Generic[ShapeType]): shape: ShapeType if __name__ == "__main__": args = tyro.cli(Args[Triangle]) print(args) .. raw:: html
    $ python ./02_generics.py --help
    usage: ./02_generics.py [-h] [OPTIONS]
    
     options ───────────────────────────────────────────────╮
     -h, --help              show this help message and exit 
    ─────────────────────────────────────────────────────────
     shape.a options ───────────────────────────────────────╮
     --shape.a.x FLOAT       (required)                      
     --shape.a.y FLOAT       (required)                      
     --shape.a.z FLOAT       (required)                      
     --shape.a.frame-id STR  (required)                      
    ─────────────────────────────────────────────────────────
     shape.b options ───────────────────────────────────────╮
     --shape.b.x FLOAT       (required)                      
     --shape.b.y FLOAT       (required)                      
     --shape.b.z FLOAT       (required)                      
     --shape.b.frame-id STR  (required)                      
    ─────────────────────────────────────────────────────────
     shape.c options ───────────────────────────────────────╮
     --shape.c.x FLOAT       (required)                      
     --shape.c.y FLOAT       (required)                      
     --shape.c.z FLOAT       (required)                      
     --shape.c.frame-id STR  (required)                      
    ─────────────────────────────────────────────────────────
    
.. _example-03_generic_subcommands: Generic Subcommands ------------------- Just like standard classes, generic classes within unions can be selected between using subcommands. .. code-block:: python :linenos: # 03_generic_subcommands.py import dataclasses from pathlib import Path import tyro @dataclasses.dataclass class Sgd: lr: float = 1e-4 @dataclasses.dataclass class Adam: lr: float = 3e-4 betas: tuple[float, float] = (0.9, 0.999) @dataclasses.dataclass class Experiment[OptimizerT: (Adam, Sgd)]: path: Path opt: OptimizerT if __name__ == "__main__": args = tyro.cli(Experiment[Adam] | Experiment[Sgd]) print(args) .. raw:: html
    $ python ./03_generic_subcommands.py --help
    usage: ./03_generic_subcommands.py [-h] {experiment-adam,experiment-sgd}
    
     options ────────────────────────────────────────────╮
     -h, --help           show this help message and exit 
    ──────────────────────────────────────────────────────
     subcommands ────────────────────────────────────────╮
     (required)                                           
     ──────────────────────────────────────────────────── 
     {experiment-adam,experiment-sgd}                     
         experiment-adam                                  
         experiment-sgd                                   
    ──────────────────────────────────────────────────────
    
.. raw:: html
    $ python ./03_generic_subcommands.py experiment-adam --help
    usage: ./03_generic_subcommands.py experiment-adam [-h] --path PATH [--opt.lr FLOAT] [--opt.betas FLOAT FLOAT]
    
     options ────────────────────────────────────────────────╮
     -h, --help               show this help message and exit 
     --path PATH              (required)                      
    ──────────────────────────────────────────────────────────
     opt options ────────────────────────────────────────────╮
     --opt.lr FLOAT           (default: 0.0003)               
     --opt.betas FLOAT FLOAT  (default: 0.9 0.999)            
    ──────────────────────────────────────────────────────────
    
.. raw:: html
    $ python ./03_generic_subcommands.py experiment-sgd --help
    usage: ./03_generic_subcommands.py experiment-sgd [-h] --path PATH [--opt.lr FLOAT]
    
     options ───────────────────────────────────────╮
     -h, --help      show this help message and exit 
     --path PATH     (required)                      
    ─────────────────────────────────────────────────
     opt options ───────────────────────────────────╮
     --opt.lr FLOAT  (default: 0.0001)               
    ─────────────────────────────────────────────────
    
.. raw:: html
    $ python ./03_generic_subcommands.py experiment-adam --path /tmp --opt.lr 1e-3
    Experiment(path=PosixPath('/tmp'), opt=Adam(lr=0.001, betas=(0.9, 0.999)))