mirror of
https://github.com/python/cpython
synced 2026-09-29 12:10:30 +03:00
bpo-43766: Implement PEP 647 (User-Defined Type Guards) in typing.py (#25282)
This commit is contained in:
parent
d92513390a
commit
05ab4b60ab
5 changed files with 175 additions and 0 deletions
|
|
@ -119,6 +119,7 @@ __all__ = [
|
|||
'Text',
|
||||
'TYPE_CHECKING',
|
||||
'TypeAlias',
|
||||
'TypeGuard',
|
||||
]
|
||||
|
||||
# The pseudo-submodules 're' and 'io' are part of the public
|
||||
|
|
@ -567,6 +568,54 @@ def Concatenate(self, parameters):
|
|||
return _ConcatenateGenericAlias(self, parameters)
|
||||
|
||||
|
||||
@_SpecialForm
|
||||
def TypeGuard(self, parameters):
|
||||
"""Special typing form used to annotate the return type of a user-defined
|
||||
type guard function. ``TypeGuard`` only accepts a single type argument.
|
||||
At runtime, functions marked this way should return a boolean.
|
||||
|
||||
``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static
|
||||
type checkers to determine a more precise type of an expression within a
|
||||
program's code flow. Usually type narrowing is done by analyzing
|
||||
conditional code flow and applying the narrowing to a block of code. The
|
||||
conditional expression here is sometimes referred to as a "type guard".
|
||||
|
||||
Sometimes it would be convenient to use a user-defined boolean function
|
||||
as a type guard. Such a function should use ``TypeGuard[...]`` as its
|
||||
return type to alert static type checkers to this intention.
|
||||
|
||||
Using ``-> TypeGuard`` tells the static type checker that for a given
|
||||
function:
|
||||
|
||||
1. The return value is a boolean.
|
||||
2. If the return value is ``True``, the type of its argument
|
||||
is the type inside ``TypeGuard``.
|
||||
|
||||
For example::
|
||||
|
||||
def is_str(val: Union[str, float]):
|
||||
# "isinstance" type guard
|
||||
if isinstance(val, str):
|
||||
# Type of ``val`` is narrowed to ``str``
|
||||
...
|
||||
else:
|
||||
# Else, type of ``val`` is narrowed to ``float``.
|
||||
...
|
||||
|
||||
Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower
|
||||
form of ``TypeA`` (it can even be a wider form) and this may lead to
|
||||
type-unsafe results. The main reason is to allow for things like
|
||||
narrowing ``List[object]`` to ``List[str]`` even though the latter is not
|
||||
a subtype of the former, since ``List`` is invariant. The responsibility of
|
||||
writing type-safe type guards is left to the user.
|
||||
|
||||
``TypeGuard`` also works with type variables. For more information, see
|
||||
PEP 647 (User-Defined Type Guards).
|
||||
"""
|
||||
item = _type_check(parameters, f'{self} accepts only single type.')
|
||||
return _GenericAlias(self, (item,))
|
||||
|
||||
|
||||
class ForwardRef(_Final, _root=True):
|
||||
"""Internal wrapper to hold a forward reference."""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue