Skip to content

[3.11] typing docs: Move some classes out of the "Generics" section (GH-104707) #104721

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 21, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 125 additions & 122 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,21 @@ These can be used as types in annotations and do not support ``[]``.
avoiding type checker errors with classes that can duck type anywhere or
are highly dynamic.

.. data:: AnyStr

``AnyStr`` is a :ref:`constrained type variable <typing-constrained-typevar>` defined as
``AnyStr = TypeVar('AnyStr', str, bytes)``.

It is meant to be used for functions that may accept any kind of string
without allowing different kinds of strings to mix. For example::

def concat(a: AnyStr, b: AnyStr) -> AnyStr:
return a + b

concat(u"foo", u"bar") # Ok, output has type 'unicode'
concat(b"foo", b"bar") # Ok, output has type 'bytes'
concat(u"foo", b"bar") # Error, cannot mix unicode and bytes

.. data:: LiteralString

Special type that includes only literal strings. A string
Expand Down Expand Up @@ -912,13 +927,13 @@ These can be used as types in annotations using ``[]``, each having a unique syn
# We don't need to pass in the lock ourselves thanks to the decorator.
sum_threadsafe([1.1, 2.2, 3.3])

.. versionadded:: 3.10
.. versionadded:: 3.10

.. seealso::
.. seealso::

* :pep:`612` -- Parameter Specification Variables (the PEP which introduced
``ParamSpec`` and ``Concatenate``).
* :class:`ParamSpec` and :class:`Callable`.
* :pep:`612` -- Parameter Specification Variables (the PEP which introduced
``ParamSpec`` and ``Concatenate``).
* :class:`ParamSpec` and :class:`Callable`.


.. class:: Type(Generic[CT_co])
Expand Down Expand Up @@ -1203,6 +1218,34 @@ These can be used as types in annotations using ``[]``, each having a unique syn
.. versionadded:: 3.10


.. data:: Unpack

A typing operator that conceptually marks an object as having been
unpacked. For example, using the unpack operator ``*`` on a
:class:`type variable tuple <TypeVarTuple>` is equivalent to using ``Unpack``
to mark the type variable tuple as having been unpacked::

Ts = TypeVarTuple('Ts')
tup: tuple[*Ts]
# Effectively does:
tup: tuple[Unpack[Ts]]

In fact, ``Unpack`` can be used interchangeably with ``*`` in the context
of :class:`typing.TypeVarTuple <TypeVarTuple>` and
:class:`builtins.tuple <tuple>` types. You might see ``Unpack`` being used
explicitly in older versions of Python, where ``*`` couldn't be used in
certain places::

# In older versions of Python, TypeVarTuple and Unpack
# are located in the `typing_extensions` backports package.
from typing_extensions import TypeVarTuple, Unpack

Ts = TypeVarTuple('Ts')
tup: tuple[*Ts] # Syntax error on Python <= 3.10!
tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible

.. versionadded:: 3.11

Building generic types
""""""""""""""""""""""

Expand Down Expand Up @@ -1404,32 +1447,6 @@ These are not used in annotations. They are building blocks for creating generic

.. versionadded:: 3.11

.. data:: Unpack

A typing operator that conceptually marks an object as having been
unpacked. For example, using the unpack operator ``*`` on a
:class:`type variable tuple <TypeVarTuple>` is equivalent to using ``Unpack``
to mark the type variable tuple as having been unpacked::

Ts = TypeVarTuple('Ts')
tup: tuple[*Ts]
# Effectively does:
tup: tuple[Unpack[Ts]]

In fact, ``Unpack`` can be used interchangeably with ``*`` in the context
of types. You might see ``Unpack`` being used explicitly in older versions
of Python, where ``*`` couldn't be used in certain places::

# In older versions of Python, TypeVarTuple and Unpack
# are located in the `typing_extensions` backports package.
from typing_extensions import TypeVarTuple, Unpack

Ts = TypeVarTuple('Ts')
tup: tuple[*Ts] # Syntax error on Python <= 3.10!
tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible

.. versionadded:: 3.11

.. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False)

Parameter specification variable. A specialized version of
Expand Down Expand Up @@ -1528,97 +1545,6 @@ These are not used in annotations. They are building blocks for creating generic
.. versionadded:: 3.10


.. data:: AnyStr

``AnyStr`` is a :ref:`constrained type variable <typing-constrained-typevar>` defined as
``AnyStr = TypeVar('AnyStr', str, bytes)``.

It is meant to be used for functions that may accept any kind of string
without allowing different kinds of strings to mix. For example::

def concat(a: AnyStr, b: AnyStr) -> AnyStr:
return a + b

concat(u"foo", u"bar") # Ok, output has type 'unicode'
concat(b"foo", b"bar") # Ok, output has type 'bytes'
concat(u"foo", b"bar") # Error, cannot mix unicode and bytes

.. class:: Protocol(Generic)

Base class for protocol classes. Protocol classes are defined like this::

class Proto(Protocol):
def meth(self) -> int:
...

Such classes are primarily used with static type checkers that recognize
structural subtyping (static duck-typing), for example::

class C:
def meth(self) -> int:
return 0

def func(x: Proto) -> int:
return x.meth()

func(C()) # Passes static type check

See :pep:`544` for more details. Protocol classes decorated with
:func:`runtime_checkable` (described later) act as simple-minded runtime
protocols that check only the presence of given attributes, ignoring their
type signatures.

Protocol classes can be generic, for example::

class GenProto(Protocol[T]):
def meth(self) -> T:
...

.. versionadded:: 3.8

.. decorator:: runtime_checkable

Mark a protocol class as a runtime protocol.

Such a protocol can be used with :func:`isinstance` and :func:`issubclass`.
This raises :exc:`TypeError` when applied to a non-protocol class. This
allows a simple-minded structural check, very similar to "one trick ponies"
in :mod:`collections.abc` such as :class:`~collections.abc.Iterable`. For example::

@runtime_checkable
class Closable(Protocol):
def close(self): ...

assert isinstance(open('/some/file'), Closable)

@runtime_checkable
class Named(Protocol):
name: str

import threading
assert isinstance(threading.Thread(name='Bob'), Named)

.. note::

:func:`!runtime_checkable` will check only the presence of the required
methods or attributes, not their type signatures or types.
For example, :class:`ssl.SSLObject`
is a class, therefore it passes an :func:`issubclass`
check against :data:`Callable`. However, the
``ssl.SSLObject.__init__`` method exists only to raise a
:exc:`TypeError` with a more informative message, therefore making
it impossible to call (instantiate) :class:`ssl.SSLObject`.

.. note::

An :func:`isinstance` check against a runtime-checkable protocol can be
surprisingly slow compared to an ``isinstance()`` check against
a non-protocol class. Consider using alternative idioms such as
:func:`hasattr` calls for structural checks in performance-sensitive
code.

.. versionadded:: 3.8

Other special directives
""""""""""""""""""""""""

Expand Down Expand Up @@ -1707,6 +1633,83 @@ These are not used in annotations. They are building blocks for declaring types.
.. versionchanged:: 3.10
``NewType`` is now a class rather than a function.

.. class:: Protocol(Generic)

Base class for protocol classes. Protocol classes are defined like this::

class Proto(Protocol):
def meth(self) -> int:
...

Such classes are primarily used with static type checkers that recognize
structural subtyping (static duck-typing), for example::

class C:
def meth(self) -> int:
return 0

def func(x: Proto) -> int:
return x.meth()

func(C()) # Passes static type check

See :pep:`544` for more details. Protocol classes decorated with
:func:`runtime_checkable` (described later) act as simple-minded runtime
protocols that check only the presence of given attributes, ignoring their
type signatures.

Protocol classes can be generic, for example::

class GenProto(Protocol[T]):
def meth(self) -> T:
...

.. versionadded:: 3.8

.. decorator:: runtime_checkable

Mark a protocol class as a runtime protocol.

Such a protocol can be used with :func:`isinstance` and :func:`issubclass`.
This raises :exc:`TypeError` when applied to a non-protocol class. This
allows a simple-minded structural check, very similar to "one trick ponies"
in :mod:`collections.abc` such as :class:`~collections.abc.Iterable`. For example::

@runtime_checkable
class Closable(Protocol):
def close(self): ...

assert isinstance(open('/some/file'), Closable)

@runtime_checkable
class Named(Protocol):
name: str

import threading
assert isinstance(threading.Thread(name='Bob'), Named)

.. note::

:func:`!runtime_checkable` will check only the presence of the required
methods or attributes, not their type signatures or types.
For example, :class:`ssl.SSLObject`
is a class, therefore it passes an :func:`issubclass`
check against :data:`Callable`. However, the
``ssl.SSLObject.__init__`` method exists only to raise a
:exc:`TypeError` with a more informative message, therefore making
it impossible to call (instantiate) :class:`ssl.SSLObject`.

.. note::

An :func:`isinstance` check against a runtime-checkable protocol can be
surprisingly slow compared to an ``isinstance()`` check against
a non-protocol class. Consider using alternative idioms such as
:func:`hasattr` calls for structural checks in performance-sensitive
code.

.. versionadded:: 3.8


.. class:: TypedDict(dict)

Special construct to add type hints to a dictionary.
Expand Down