Skip to content
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

Adds docs about := and TypeGuard #11161

Merged
merged 1 commit into from
Sep 21, 2021
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
35 changes: 34 additions & 1 deletion docs/source/type_narrowing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ Type narrowing is contextual. For example, based on the condition, mypy will nar
# Back outside of the ``if`` statement, the type isn't narrowed:
reveal_type(arg) # Revealed type: "builtins.object"

Mypy understands the implications `return` or exception raising can have for what type an object could be:
Mypy understands the implications ``return`` or exception raising can have
for what type an object could be:

.. code-block:: python

Expand Down Expand Up @@ -295,3 +296,35 @@ TypeGuards as methods

def is_child(instance: Parent) -> TypeGuard[Child]:
return isinstance(instance, Child)

Assignment expressions as TypeGuards
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sometimes you might need to create a new variable and narrow it
to some specific type at the same time.
This can be achieved by using ``TypeGuard`` together
with `:= operator <https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions>`_.

.. code-block:: python

from typing import TypeGuard # use `typing_extensions` for `python<3.10`

def is_float(a: object) -> TypeGuard[float]:
return isinstance(a, float)

def main(a: object) -> None:
if is_float(x := a):
reveal_type(x) # N: Revealed type is 'builtins.float'
reveal_type(a) # N: Revealed type is 'builtins.object'
reveal_type(x) # N: Revealed type is 'builtins.object'
reveal_type(a) # N: Revealed type is 'builtins.object'

What happens here?

1. We create a new variable ``x`` and assign a value of ``a`` to it
2. We run ``is_float()`` type guard on ``x``
3. It narrows ``x`` to be ``float`` in the ``if`` context and does not touch ``a``

.. note::

The same will work with ``isinstance(x := a, float)`` as well.