Hi,
First of all, sorry for not commenting on this earlier.
I only became aware of this PEP yesterday.
I like the general idea of adding a marker to show that a boolean
function narrows the type of one (or more?) of its arguments.
However, the suggested approach seems clunky and impairs readability.
It impairs readability, because it muddles the return type.
The function in the example returns a bool.
The annotation is also misleading as the annotation is on the return
type, not on the parameter that is narrowed.
At a glance, most programmers should be able to work out what
def is_str_list(val: List[object]) -> bool:
returns.
But,
def is_str_list(val: List[object]) -> TypeGuard[List[str]]:
is likely to confuse and require careful reading.
Type hints are for humans as well as type checkers.
Technical review.
-----------------
For an annotation of this kind to be useful to a checker, that checker
must perform both flow-sensitive and call-graph analysis. Therefore it
is theoretically possible to remove the annotation altogether, using the
following approach:
1. Scan the code looking for functions that return boolean and
potentially narrow the type of their arguments.
2. Inline those functions in the analysis
3. Rely on pre-existing flow-senstive analysis to determine the correct
types.
However, explicit is better and implicit. So some sort of annotation
seems sensible.
I would contend that the minimal:
@narrows
def is_str_list(val: List[object]) -> bool:
is sufficient for a checker, as the checker can inline anything marked
@narrows.
Plus, it does not mislead the reader by mangling the return type.
An alternative, and more explicit, approach would be to use variable
annotations.
So:
def is_str_list(val: List[object]) -> bool:
"""Determines whether all objects in the list are strings"""
return all(isinstance(x, str) for x in val)
might become:
def is_str_list(val: List[object]) -> bool:
"""Determines whether all objects in the list are strings"""
val: NarrowsTo[List[str]]
return all(isinstance(x, str) for x in val)
Although the above lacks flow control and is thus ambiguous without the
convention that `NarrowsTo` only applies if the result is True.
An alternative formulation would require the annotation to dominate the
function exit:
def is_str_list(val: List[object]) -> bool:
"""Determines whether all objects in the list are strings"""
if all(isinstance(x, str) for x in val):
val: NarrowsTo[List[str]]
return True
return False
This is unambiguous.
Finally, I would ask for a change of name.
The "Type" part is redundant, since it is a type annotation, and the
"Guard" part is incorrect. It is only a guard when used, the function
itself is a predicate that narrows the type of an argument. "Narrows" or
"NarrowsTo" would be better.
Cheers,
Mark.
On 09/02/2021 4:21 pm, Guido van Rossum wrote:
I think we have reached consensus on PEP 647 in typing-sig. We have
implementations for mypy and pyright, not sure about the rest. This PEP
does not affect CPython directly except for the addition of one special
item (TypeGuard) to typing.py -- it would be nice to get that in the
3.10 stdlib.
I'm CC'ing python-dev here to see if there are any further comments; if
not, we can initiate the approval process by creating an issue at
https://github.com/python/steering-council.
--
--Guido van Rossum (python.org/~guido <http://python.org/~guido>)
/Pronouns: he/him //(why is my pronoun here?)/
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/NOLCFYLYAQQHXISNMPYCEOAZ7ZPFCGUW/
Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/4LKI6IGCT7JHH5C3YQPA4SXHDQWJC5Q2/
Code of Conduct: http://python.org/psf/codeofconduct/