Generics¶
tyro
’s understanding of Python’s type system includes user-defined
parameterized types, which can reduce boilerplate and improve type safety.
Generics (3.12+)¶
This example uses syntax introduced in Python 3.12 (PEP 695).
Note
If used in conjunction with from __future__ import annotations
, the updated type parameter syntax requires Python 3.12.4 or newer. For technical details, see this CPython PR.
1# 01_generics_py312.py
2import dataclasses
3
4import tyro
5
6@dataclasses.dataclass
7class Point3[ScalarType: (int, float)]:
8 x: ScalarType
9 y: ScalarType
10 z: ScalarType
11 frame_id: str
12
13@dataclasses.dataclass
14class Triangle:
15 a: Point3[float]
16 b: Point3[float]
17 c: Point3[float]
18
19@dataclasses.dataclass
20class Args[ShapeType]:
21 shape: ShapeType
22
23if __name__ == "__main__":
24 args = tyro.cli(Args[Triangle])
25 print(args)
$ 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) │ ╰─────────────────────────────────────────────────────────╯
Generics (Legacy)¶
The legacy typing.Generic
and typing.TypeVar
syntax for
generic types is also supported.
1# 02_generics.py
2import dataclasses
3from typing import Generic, TypeVar
4
5import tyro
6
7ScalarType = TypeVar("ScalarType", int, float)
8ShapeType = TypeVar("ShapeType")
9
10@dataclasses.dataclass(frozen=True)
11class Point3(Generic[ScalarType]):
12 x: ScalarType
13 y: ScalarType
14 z: ScalarType
15 frame_id: str
16
17@dataclasses.dataclass(frozen=True)
18class Triangle:
19 a: Point3[float]
20 b: Point3[float]
21 c: Point3[float]
22
23@dataclasses.dataclass(frozen=True)
24class Args(Generic[ShapeType]):
25 shape: ShapeType
26
27if __name__ == "__main__":
28 args = tyro.cli(Args[Triangle])
29 print(args)
$ 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) │ ╰─────────────────────────────────────────────────────────╯