8000 Typing: improve docs on the type of class objects by AlexWaygood · Pull Request #106081 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

Typing: improve docs on the type of class objects #106081

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 1 commit into from
Jun 26, 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
108 changes: 59 additions & 49 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,52 @@ of the same type ``T``, use ``tuple[T, ...]``. To denote an empty tuple, use
z = (1, 2, 3)< 8000 /span>
z = ()

.. _type-of-class-objects:

The type of class objects
=========================

A variable annotated with ``C`` may accept a value of type ``C``. In
contrast, a variable annotated with ``type[C]`` (or
:class:`typing.Type[C] <Type>`) may accept values that are classes
themselves -- specifically, it will accept the *class object* of ``C``. For
example::

a = 3 # Has type ``int```
b = int # Has type ``type[int]``
c = type(a) # Also has type ``type[int]``

Note that ``type[C]`` is covariant::

class User: ...
class ProUser(User): ...
class TeamUser(User): ...

def make_new_user(user_class: type[User]) -> User:
# ...
return user_class()

make_new_user(User) # OK
make_new_user(ProUser) # Also OK: ``type[ProUser]`` is a subtype of ``type[User]``
make_new_user(TeamUser) # Still fine
make_new_user(User()) # Error: expected ``type[User]`` but got ``User``
make_new_user(int) # Error: ``type[int]`` is not a subtype of ``type[User]``

The only legal parameters for :class:`type` are classes, :data:`Any`,
:ref:`type variables <generics>`, and unions of any of these types.
For example::

def new_non_team_user(user_class: type[BasicUser | ProUser]): ...

new_non_team_user(BasicUser) # OK
new_non_team_user(ProUser) # OK
new_non_team_user(TeamUser) # Error: ``type[TeamUser]`` is not a subtype
# of ``type[BasicUser | ProUser]``
new_non_team_user(User) # Also an error

``type[Any]`` is equivalent to :class:`type`, which is the root of Python's
:ref:`metaclass hierarchy <metaclasses>`.

.. _user-defined-generics:

User-defined generic types
Expand Down Expand Up @@ -1093,55 +1139,6 @@ These can be used as types in annotations. They all support subscription using
``ParamSpec`` and ``Concatenate``).
* :class:`ParamSpec` and :class:`Callable`.


.. class:: Type(Generic[CT_co])

Deprecated alias to :class:`type`.

A variable annotated with ``C`` may accept a value of type ``C``. In
contrast, a variable annotated with ``type[C]`` or ``Type[C]`` may accept values that are
classes themselves -- specifically, it will accept the *class object* of
``C``. For example::

a = 3 # Has type 'int'
b = int # Has type 'Type[int]'
c = type(a) # Also has type 'Type[int]'

Note that ``Type[C]`` is covariant::

class User: ...
class BasicUser(User): ...
class ProUser(User): ...
class TeamUser(User): ...

# Accepts User, BasicUser, ProUser, TeamUser, ...
def make_new_user(user_class: Type[User]) -> User:
# ...
return user_class()

The fact that ``Type[C]`` is covariant implies that all subclasses of
``C`` should implement the same constructor signature and class method
signatures as ``C``. The type checker should flag violations of this,
but should also allow constructor calls in subclasses that match the
constructor calls in the indicated base class. How the type checker is
required to handle this particular case may change in future revisions of
:pep:`484`.

The only legal parameters for :class:`Type` are classes, :data:`Any`,
:ref:`type variables <generics>`, and unions of any of these types.
For example::

def new_non_team_user(user_class: Type[BasicUser | ProUser]): ...

``Type[Any]`` is equivalent to ``Type`` which in turn is equivalent
to ``type``, which is the root of Python's metaclass hierarchy.

.. versionadded:: 3.5.2

.. deprecated:: 3.9
:class:`builtins.type <type>` now supports subscripting (``[]``).
See :pep:`585` and :ref:`types-genericalias`.

.. data:: Literal

Special typing form to define "literal types".
Expand Down Expand Up @@ -3189,6 +3186,19 @@ Aliases to built-in types
:class:`builtins.tuple <tuple>` now supports subscripting (``[]``).
See :pep:`585` and :ref:`types-genericalias`.

.. class:: Type(Generic[CT_co])

Deprecated alias to :class:`type`.

See :ref:`type-of-class-objects` for details on using :class:`type` or
``typing.Type`` in type annotations.

.. versionadded:: 3.5.2

.. deprecated:: 3.9
:class:`builtins.type <type>` now supports subscripting (``[]``).
See :pep:`585` and :ref:`types-genericalias`.

.. _corresponding-to-types-in-collections:

Aliases to types in :mod:`collections`
Expand Down
0