Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python type hints - better syntax for cast()?

I recently started using type hints in my code, and have so far found them to be (mostly) very helpful.

However, one thing that I really do not like is the syntax to force the type checker to assume that a variable is of a certain type. Given this example:

import itertools
from typing import Iterable, Tuple
x: Iterable[Tuple[str, str]] = itertools.combinations('abc', 2)
# error: Incompatible types in assignment (expression has type "Iterable[Tuple[str, ...]]", variable has type "List[Tuple[str, str]]")

As far as I can tell, the recommended way to work around this is to explicitly cast the object to force the type checker to use the specified type, e.g.:

import itertools
from typing import Iterable, Tuple, cast
x = cast(Iterable[Tuple[str, str]], itertools.combinations('abc', 2))

I personally find this solution to be a bit gross. My primary concern is that, to the inexperienced reader, it is not clear that the cast is purely there to help the static analyzer. (If I didn't already know, I would assume based on the name and context that it is converting and doing a copy into an object of the specified type, when really there is no runtime cost.)

cast looks like any old function call. When I see that a function is being called on a value, I expect the value to be mutated and/or some other side-effects to occur, but in this case the only side effect is that mypy stops complaining. Type hints themselves have a distinct syntax, but I feel that this blurs the lines with a mixture of the new typing syntax and traditional python syntax. (It's already a bit blurry since you have to import the types and can compose them, but that's another discussion.)

Is there an alternative syntax for cast-like behavior? I haven't found anything, but I was hoping for something like:

x1 = itertools.combinations('abc', 2)) # cast: Iterable[Tuple[str, str]] 

x2: Iterable[Tuple[str, str]] = itertools.combinations('abc', 2)) # type: cast

x3: Cast[Iterable[Tuple[str, str]]] = itertools.combinations('abc', 2))
like image 902
0x5453 Avatar asked Apr 01 '19 18:04

0x5453


People also ask

Is it good practice to use type hints in Python?

Type hints work best in modern Pythons. Annotations were introduced in Python 3.0, and it's possible to use type comments in Python 2.7. Still, improvements like variable annotations and postponed evaluation of type hints mean that you'll have a better experience doing type checks using Python 3.6 or even Python 3.7.

What is cast () in Python?

Prerequisites: Python Data Types. Type Casting is the method to convert the variable data type into a certain data type in order to the operation required to be performed by users.

How do you write hints in Python?

Here's how you can add type hints to our function: Add a colon and a data type after each function parameter. Add an arrow ( -> ) and a data type after the function to specify the return data type.

Do type hints slow down Python?

So in short: no, they will not cause any run-time effects, unless you explicitly make use of them. That is incorrect. They need to be resolved when loading the code and they are kept in memory. After the loading there shouldn't be slowdowns.


1 Answers

Actually the latest version of Mypy does return the correct type Iterator[Tuple[str, str]].

This change was introduced to Typeshed in PR https://github.com/python/typeshed/pull/4309.

If you cannot update mypy to the latest version you can checkout the latest version from typeshed and use the config option custom_typeshed_dir.

See https://mypy.readthedocs.io/en/stable/config_file.html#confval-custom_typeshed_dir for more details.

like image 92
Sebastian Kreft Avatar answered Sep 23 '22 17:09

Sebastian Kreft