Skip to content

Commit 94c46d7

Browse files
authored
Use built-in generic aliases, use shorthand for unions (#2098)
1 parent ecc2129 commit 94c46d7

File tree

1 file changed

+33
-33
lines changed

1 file changed

+33
-33
lines changed

docs/guides/libraries.rst

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -232,15 +232,15 @@ is obvious from the context:
232232
assigned only once and is either annotated with ``Final`` or is named
233233
in all-caps. A constant that is not assigned a simple literal value
234234
requires explicit annotations, preferably with a ``Final`` annotation
235-
(e.g. ``WOODWINDS: Final[List[str]] = ['Oboe', 'Bassoon']``).
235+
(e.g. ``WOODWINDS: Final[list[str]] = ['Oboe', 'Bassoon']``).
236236
- Enum values within an Enum class do not require annotations because
237237
they take on the type of the Enum class.
238238
- Type aliases do not require annotations. A type alias is a symbol
239239
that is defined at a module level with a single assignment where the
240240
assigned value is an instantiable type, as opposed to a class
241241
instance
242-
(e.g. ``Foo = Callable[[Literal["a", "b"]], Union[int, str]]`` or
243-
``Bar = Optional[MyGenericClass[int]]``).
242+
(e.g. ``Foo = Callable[[Literal["a", "b"]], int | str]`` or
243+
``Bar = MyGenericClass[int] | None``).
244244
- The “self” parameter in an instance method and the “cls” parameter in
245245
a class method do not require an explicit annotation.
246246
- The return type for an ``__init__`` method does not need to be
@@ -262,21 +262,21 @@ Examples of known and unknown types
262262
a = [3, 4, 5]
263263
264264
# Variable with known type
265-
a: List[int] = [3, 4, 5]
265+
a: list[int] = [3, 4, 5]
266266
267267
# Type alias with partially unknown type (because type
268268
# arguments are missing for list and dict)
269-
DictOrList = Union[list, dict]
269+
DictOrList = list | dict
270270
271271
# Type alias with known type
272-
DictOrList = Union[List[Any], Dict[str, Any]]
272+
DictOrList = list[Any] | dict[str, Any]
273273
274274
# Generic type alias with known type
275275
_T = TypeVar("_T")
276-
DictOrList = Union[List[_T], Dict[str, _T]]
276+
DictOrList = list[_T] | dict[str, _T]
277277
278278
# Function with known type
279-
def func(a: Optional[int], b: Dict[str, float] = {}) -> None:
279+
def func(a: int | None, b: dict[str, float] = {}) -> None:
280280
pass
281281
282282
# Function with partially unknown type (because type annotations
@@ -291,7 +291,7 @@ Examples of known and unknown types
291291
292292
# Function with partially unknown type (because return type
293293
# annotation is missing)
294-
def func(a: int, b: Dict[str, float]):
294+
def func(a: int, b: dict[str, float]):
295295
pass
296296
297297
# Decorator with partially unknown type (because type annotations
@@ -366,7 +366,7 @@ Wide vs. Narrow Types
366366
In type theory, when comparing two types that are related to each other,
367367
the “wider” type is the one that is more general, and the “narrower”
368368
type is more specific. For example, ``Sequence[str]`` is a wider type
369-
than ``List[str]`` because all ``List`` objects are also ``Sequence``
369+
than ``list[str]`` because all ``list`` objects are also ``Sequence``
370370
objects, but the converse is not true. A subclass is narrower than a
371371
class it derives from. A union of types is wider than the individual
372372
types that comprise the union.
@@ -375,21 +375,21 @@ In general, a function input parameter should be annotated with the
375375
widest possible type supported by the implementation. For example, if
376376
the implementation requires the caller to provide an iterable collection
377377
of strings, the parameter should be annotated as ``Iterable[str]``, not
378-
as ``List[str]``. The latter type is narrower than necessary, so if a
378+
as ``list[str]``. The latter type is narrower than necessary, so if a
379379
user attempts to pass a tuple of strings (which is supported by the
380380
implementation), a type checker will complain about a type
381381
incompatibility.
382382

383383
As a specific application of the “use the widest type possible” rule,
384384
libraries should generally use immutable forms of container types
385385
instead of mutable forms (unless the function needs to modify the
386-
container). Use ``Sequence`` rather than ``List``, ``Mapping`` rather
387-
than ``Dict``, etc. Immutable containers allow for more flexibility
386+
container). Use ``Sequence`` rather than ``list``, ``Mapping`` rather
387+
than ``dict``, etc. Immutable containers allow for more flexibility
388388
because their type parameters are covariant rather than invariant. A
389-
parameter that is typed as ``Sequence[Union[str, int]]`` can accept a
390-
``List[int]``, ``Sequence[str]``, and a ``Sequence[int]``. But a
391-
parameter typed as ``List[Union[str, int]]`` is much more restrictive
392-
and accepts only a ``List[Union[str, int]]``.
389+
parameter that is typed as ``Sequence[str | int]`` can accept a
390+
``list[int]``, ``Sequence[str]``, and a ``Sequence[int]``. But a
391+
parameter typed as ``list[str | int]`` is much more restrictive
392+
and accepts only a ``list[str | int]``.
393393

394394
Overloads
395395
---------
@@ -409,7 +409,7 @@ specified only by name, use the keyword-only separator (``*``).
409409

410410
.. code:: python
411411
412-
def create_user(age: int, *, dob: Optional[date] = None):
412+
def create_user(age: int, *, dob: date | None = None):
413413
...
414414
415415
.. _annotating-decorators:
@@ -455,14 +455,14 @@ from creating decorators that mutate function signatures in this manner.
455455
Aliasing Decorators
456456
-------------------
457457

458-
When writing a library with a couple of decorator factories
458+
When writing a library with a couple of decorator factories
459459
(i.e. functions returning decorators, like ``complex_decorator`` from the
460-
:ref:`annotating-decorators` section) it may be tempting to create a shortcut
461-
for a decorator.
460+
:ref:`annotating-decorators` section) it may be tempting to create a shortcut
461+
for a decorator.
462462

463463
Different type checkers handle :data:`TypeAlias <typing.TypeAlias>` involving
464464
:class:`Callable <collections.abc.Callable>` in a
465-
different manner, so the most portable and easy way to create a shortcut
465+
different manner, so the most portable and easy way to create a shortcut
466466
is to define a callable :class:`Protocol <typing.Protocol>` as described in the
467467
:ref:`callback-protocols` section of the Typing Specification.
468468

@@ -471,7 +471,7 @@ There is already a :class:`Protocol <typing.Protocol>` called
471471
`_typeshed <https://github.com/python/typeshed/blob/main/stdlib/_typeshed/README.md>`_:
472472

473473
.. code:: python
474-
474+
475475
from typing import TYPE_CHECKING
476476
477477
if TYPE_CHECKING:
@@ -485,17 +485,17 @@ There is already a :class:`Protocol <typing.Protocol>` called
485485
"""
486486
...
487487
488-
For non-trivial decorators with custom logic, it is still possible
488+
For non-trivial decorators with custom logic, it is still possible
489489
to define a custom protocol using :class:`ParamSpec <typing.ParamSpec>`
490490
and :data:`Concatenate <typing.Concatenate>` mechanisms:
491491

492492
.. code:: python
493493
494494
class Client: ...
495-
495+
496496
P = ParamSpec("P")
497497
R = TypeVar("R")
498-
498+
499499
class PClientInjector(Protocol):
500500
def __call__(self, _: Callable[Concatenate[Client, P], R], /) -> Callable[P, R]:
501501
...
@@ -505,7 +505,7 @@ and :data:`Concatenate <typing.Concatenate>` mechanisms:
505505
Decorator factory is invoked with arguments like this:
506506
@inject_client("testing")
507507
def my_function(client: Client, value: int): ...
508-
508+
509509
my_function then takes only value
510510
"""
511511
@@ -534,16 +534,16 @@ annotation.
534534
.. code:: python
535535
536536
# Simple type alias
537-
FamilyPet = Union[Cat, Dog, GoldFish]
537+
FamilyPet = Cat | Dog | GoldFish
538538
539539
# Generic type alias
540-
ListOrTuple = Union[List[_T], Tuple[_T, ...]]
540+
ListOrTuple = list[_T] | tuple[_T, ...]
541541
542542
# Recursive type alias
543-
TreeNode = Union[LeafNode, List["TreeNode"]]
543+
TreeNode = LeafNode | list["TreeNode"]
544544
545545
# Explicit type alias using PEP 613 syntax
546-
StrOrInt: TypeAlias = Union[str, int]
546+
StrOrInt: TypeAlias = str | int
547547
548548
Abstract Classes and Methods
549549
----------------------------
@@ -609,14 +609,14 @@ type annotation would be redundant.
609609
610610
# All-caps constant with explicit type
611611
COLOR_FORMAT_RGB: Literal["rgb"] = "rgb"
612-
LATEST_VERSION: Tuple[int, int] = (4, 5)
612+
LATEST_VERSION: tuple[int, int] = (4, 5)
613613
614614
# Final variable with inferred type
615615
ColorFormatRgb: Final = "rgb"
616616
617617
# Final variable with explicit type
618618
ColorFormatRgb: Final[Literal["rgb"]] = "rgb"
619-
LATEST_VERSION: Final[Tuple[int, int]] = (4, 5)
619+
LATEST_VERSION: Final[tuple[int, int]] = (4, 5)
620620
621621
Typed Dictionaries, Data Classes, and Named Tuples
622622
--------------------------------------------------

0 commit comments

Comments
 (0)