mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +00:00
[3.12] Improve code examples in typing.rst
(GH-105346) (#105422)
Improve code examples in `typing.rst` (GH-105346)
(cherry picked from commit 81c81328a4
)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
a36fb691ac
commit
2cfe778d7f
1 changed files with 75 additions and 30 deletions
|
@ -2,6 +2,11 @@
|
||||||
:mod:`typing` --- Support for type hints
|
:mod:`typing` --- Support for type hints
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
|
.. testsetup:: *
|
||||||
|
|
||||||
|
import typing
|
||||||
|
from typing import *
|
||||||
|
|
||||||
.. module:: typing
|
.. module:: typing
|
||||||
:synopsis: Support for type hints (see :pep:`484`).
|
:synopsis: Support for type hints (see :pep:`484`).
|
||||||
|
|
||||||
|
@ -261,19 +266,22 @@ Callable
|
||||||
Frameworks expecting callback functions of specific signatures might be
|
Frameworks expecting callback functions of specific signatures might be
|
||||||
type hinted using ``Callable[[Arg1Type, Arg2Type], ReturnType]``.
|
type hinted using ``Callable[[Arg1Type, Arg2Type], ReturnType]``.
|
||||||
|
|
||||||
For example::
|
For example:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
|
|
||||||
def feeder(get_next_item: Callable[[], str]) -> None:
|
def feeder(get_next_item: Callable[[], str]) -> None:
|
||||||
# Body
|
... # Body
|
||||||
|
|
||||||
def async_query(on_success: Callable[[int], None],
|
def async_query(on_success: Callable[[int], None],
|
||||||
on_error: Callable[[int, Exception], None]) -> None:
|
on_error: Callable[[int, Exception], None]) -> None:
|
||||||
# Body
|
... # Body
|
||||||
|
|
||||||
async def on_update(value: str) -> None:
|
async def on_update(value: str) -> None:
|
||||||
# Body
|
... # Body
|
||||||
|
|
||||||
callback: Callable[[str], Awaitable[None]] = on_update
|
callback: Callable[[str], Awaitable[None]] = on_update
|
||||||
|
|
||||||
It is possible to declare the return type of a callable without specifying
|
It is possible to declare the return type of a callable without specifying
|
||||||
|
@ -431,11 +439,14 @@ In this case ``MyDict`` has a single parameter, ``T``.
|
||||||
|
|
||||||
Using a generic class without specifying type parameters assumes
|
Using a generic class without specifying type parameters assumes
|
||||||
:data:`Any` for each position. In the following example, ``MyIterable`` is
|
:data:`Any` for each position. In the following example, ``MyIterable`` is
|
||||||
not generic but implicitly inherits from ``Iterable[Any]``::
|
not generic but implicitly inherits from ``Iterable[Any]``:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
|
|
||||||
class MyIterable(Iterable): # Same as Iterable[Any]
|
class MyIterable(Iterable): # Same as Iterable[Any]
|
||||||
|
...
|
||||||
|
|
||||||
User-defined generic type aliases are also supported. Examples::
|
User-defined generic type aliases are also supported. Examples::
|
||||||
|
|
||||||
|
@ -701,9 +712,11 @@ These can be used as types in annotations and do not support ``[]``.
|
||||||
A string created by composing ``LiteralString``-typed objects
|
A string created by composing ``LiteralString``-typed objects
|
||||||
is also acceptable as a ``LiteralString``.
|
is also acceptable as a ``LiteralString``.
|
||||||
|
|
||||||
Example::
|
Example:
|
||||||
|
|
||||||
def run_query(sql: LiteralString) -> ...
|
.. testcode::
|
||||||
|
|
||||||
|
def run_query(sql: LiteralString) -> None:
|
||||||
...
|
...
|
||||||
|
|
||||||
def caller(arbitrary_string: str, literal_string: LiteralString) -> None:
|
def caller(arbitrary_string: str, literal_string: LiteralString) -> None:
|
||||||
|
@ -1596,9 +1609,9 @@ without the dedicated syntax, as documented below.
|
||||||
def __abs__(self) -> "Array[*Shape]": ...
|
def __abs__(self) -> "Array[*Shape]": ...
|
||||||
def get_shape(self) -> tuple[*Shape]: ...
|
def get_shape(self) -> tuple[*Shape]: ...
|
||||||
|
|
||||||
Type variable tuples can be happily combined with normal type variables::
|
Type variable tuples can be happily combined with normal type variables:
|
||||||
|
|
||||||
DType = TypeVar('DType')
|
.. testcode::
|
||||||
|
|
||||||
class Array[DType, *Shape]: # This is fine
|
class Array[DType, *Shape]: # This is fine
|
||||||
pass
|
pass
|
||||||
|
@ -1606,6 +1619,9 @@ without the dedicated syntax, as documented below.
|
||||||
class Array2[*Shape, DType]: # This would also be fine
|
class Array2[*Shape, DType]: # This would also be fine
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class Height: ...
|
||||||
|
class Width: ...
|
||||||
|
|
||||||
float_array_1d: Array[float, Height] = Array() # Totally fine
|
float_array_1d: Array[float, Height] = Array() # Totally fine
|
||||||
int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too
|
int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too
|
||||||
|
|
||||||
|
@ -1759,7 +1775,9 @@ without the dedicated syntax, as documented below.
|
||||||
|
|
||||||
The type of type aliases created through the :keyword:`type` statement.
|
The type of type aliases created through the :keyword:`type` statement.
|
||||||
|
|
||||||
Example::
|
Example:
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
|
||||||
>>> type Alias = int
|
>>> type Alias = int
|
||||||
>>> type(Alias)
|
>>> type(Alias)
|
||||||
|
@ -1769,7 +1787,9 @@ without the dedicated syntax, as documented below.
|
||||||
|
|
||||||
.. attribute:: __name__
|
.. attribute:: __name__
|
||||||
|
|
||||||
The name of the type alias::
|
The name of the type alias:
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
|
||||||
>>> type Alias = int
|
>>> type Alias = int
|
||||||
>>> Alias.__name__
|
>>> Alias.__name__
|
||||||
|
@ -2158,7 +2178,11 @@ These are not used in annotations. They are building blocks for declaring types.
|
||||||
group: list[T]
|
group: list[T]
|
||||||
|
|
||||||
To create a generic ``TypedDict`` that is compatible with Python 3.11
|
To create a generic ``TypedDict`` that is compatible with Python 3.11
|
||||||
or lower, inherit from :class:`Generic` explicitly::
|
or lower, inherit from :class:`Generic` explicitly:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
class Group(TypedDict, Generic[T]):
|
class Group(TypedDict, Generic[T]):
|
||||||
key: T
|
key: T
|
||||||
|
@ -2171,7 +2195,9 @@ These are not used in annotations. They are building blocks for declaring types.
|
||||||
.. attribute:: __total__
|
.. attribute:: __total__
|
||||||
|
|
||||||
``Point2D.__total__`` gives the value of the ``total`` argument.
|
``Point2D.__total__`` gives the value of the ``total`` argument.
|
||||||
Example::
|
Example:
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
|
||||||
>>> from typing import TypedDict
|
>>> from typing import TypedDict
|
||||||
>>> class Point2D(TypedDict): pass
|
>>> class Point2D(TypedDict): pass
|
||||||
|
@ -2201,7 +2227,9 @@ These are not used in annotations. They are building blocks for declaring types.
|
||||||
non-required keys in the same ``TypedDict`` . This is done by declaring a
|
non-required keys in the same ``TypedDict`` . This is done by declaring a
|
||||||
``TypedDict`` with one value for the ``total`` argument and then
|
``TypedDict`` with one value for the ``total`` argument and then
|
||||||
inheriting from it in another ``TypedDict`` with a different value for
|
inheriting from it in another ``TypedDict`` with a different value for
|
||||||
``total``::
|
``total``:
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
|
||||||
>>> class Point2D(TypedDict, total=False):
|
>>> class Point2D(TypedDict, total=False):
|
||||||
... x: int
|
... x: int
|
||||||
|
@ -2860,12 +2888,12 @@ Functions and decorators
|
||||||
decorated object performs runtime "magic" that
|
decorated object performs runtime "magic" that
|
||||||
transforms a class, giving it :func:`dataclasses.dataclass`-like behaviors.
|
transforms a class, giving it :func:`dataclasses.dataclass`-like behaviors.
|
||||||
|
|
||||||
Example usage with a decorator function::
|
Example usage with a decorator function:
|
||||||
|
|
||||||
T = TypeVar("T")
|
.. testcode::
|
||||||
|
|
||||||
@dataclass_transform()
|
@dataclass_transform()
|
||||||
def create_model(cls: type[T]) -> type[T]:
|
def create_model[T](cls: type[T]) -> type[T]:
|
||||||
...
|
...
|
||||||
return cls
|
return cls
|
||||||
|
|
||||||
|
@ -2969,7 +2997,9 @@ Functions and decorators
|
||||||
runtime but should be ignored by a type checker. At runtime, calling
|
runtime but should be ignored by a type checker. At runtime, calling
|
||||||
a ``@overload``-decorated function directly will raise
|
a ``@overload``-decorated function directly will raise
|
||||||
:exc:`NotImplementedError`. An example of overload that gives a more
|
:exc:`NotImplementedError`. An example of overload that gives a more
|
||||||
precise type than can be expressed using a union or a type variable::
|
precise type than can be expressed using a union or a type variable:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def process(response: None) -> None:
|
def process(response: None) -> None:
|
||||||
|
@ -2981,7 +3011,7 @@ Functions and decorators
|
||||||
def process(response: bytes) -> str:
|
def process(response: bytes) -> str:
|
||||||
...
|
...
|
||||||
def process(response):
|
def process(response):
|
||||||
<actual implementation>
|
... # actual implementation goes here
|
||||||
|
|
||||||
See :pep:`484` for more details and comparison with other typing semantics.
|
See :pep:`484` for more details and comparison with other typing semantics.
|
||||||
|
|
||||||
|
@ -3073,10 +3103,13 @@ Functions and decorators
|
||||||
This helps prevent bugs that may occur when a base class is changed without
|
This helps prevent bugs that may occur when a base class is changed without
|
||||||
an equivalent change to a child class.
|
an equivalent change to a child class.
|
||||||
|
|
||||||
For example::
|
For example:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
class Base:
|
class Base:
|
||||||
def log_status(self)
|
def log_status(self) -> None:
|
||||||
|
...
|
||||||
|
|
||||||
class Sub(Base):
|
class Sub(Base):
|
||||||
@override
|
@override
|
||||||
|
@ -3135,14 +3168,16 @@ Introspection helpers
|
||||||
|
|
||||||
The function recursively replaces all ``Annotated[T, ...]`` with ``T``,
|
The function recursively replaces all ``Annotated[T, ...]`` with ``T``,
|
||||||
unless ``include_extras`` is set to ``True`` (see :class:`Annotated` for
|
unless ``include_extras`` is set to ``True`` (see :class:`Annotated` for
|
||||||
more information). For example::
|
more information). For example:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
class Student(NamedTuple):
|
class Student(NamedTuple):
|
||||||
name: Annotated[str, 'some marker']
|
name: Annotated[str, 'some marker']
|
||||||
|
|
||||||
get_type_hints(Student) == {'name': str}
|
assert get_type_hints(Student) == {'name': str}
|
||||||
get_type_hints(Student, include_extras=False) == {'name': str}
|
assert get_type_hints(Student, include_extras=False) == {'name': str}
|
||||||
get_type_hints(Student, include_extras=True) == {
|
assert get_type_hints(Student, include_extras=True) == {
|
||||||
'name': Annotated[str, 'some marker']
|
'name': Annotated[str, 'some marker']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3169,7 +3204,9 @@ Introspection helpers
|
||||||
If ``X`` is an instance of :class:`ParamSpecArgs` or :class:`ParamSpecKwargs`,
|
If ``X`` is an instance of :class:`ParamSpecArgs` or :class:`ParamSpecKwargs`,
|
||||||
return the underlying :class:`ParamSpec`.
|
return the underlying :class:`ParamSpec`.
|
||||||
Return ``None`` for unsupported objects.
|
Return ``None`` for unsupported objects.
|
||||||
Examples::
|
Examples:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
assert get_origin(str) is None
|
assert get_origin(str) is None
|
||||||
assert get_origin(Dict[str, int]) is dict
|
assert get_origin(Dict[str, int]) is dict
|
||||||
|
@ -3188,7 +3225,9 @@ Introspection helpers
|
||||||
generic type, the order of ``(Y, Z, ...)`` may be different from the order
|
generic type, the order of ``(Y, Z, ...)`` may be different from the order
|
||||||
of the original arguments ``[Y, Z, ...]`` due to type caching.
|
of the original arguments ``[Y, Z, ...]`` due to type caching.
|
||||||
Return ``()`` for unsupported objects.
|
Return ``()`` for unsupported objects.
|
||||||
Examples::
|
Examples:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
assert get_args(int) == ()
|
assert get_args(int) == ()
|
||||||
assert get_args(Dict[int, str]) == (int, str)
|
assert get_args(Dict[int, str]) == (int, str)
|
||||||
|
@ -3200,14 +3239,20 @@ Introspection helpers
|
||||||
|
|
||||||
Check if a type is a :class:`TypedDict`.
|
Check if a type is a :class:`TypedDict`.
|
||||||
|
|
||||||
For example::
|
For example:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
class Film(TypedDict):
|
class Film(TypedDict):
|
||||||
title: str
|
title: str
|
||||||
year: int
|
year: int
|
||||||
|
|
||||||
is_typeddict(Film) # => True
|
assert is_typeddict(Film)
|
||||||
is_typeddict(list | str) # => False
|
assert not is_typeddict(list | str)
|
||||||
|
|
||||||
|
# TypedDict is a factory for creating typed dicts,
|
||||||
|
# not a typed dict itself
|
||||||
|
assert not is_typeddict(TypedDict)
|
||||||
|
|
||||||
.. versionadded:: 3.10
|
.. versionadded:: 3.10
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue