0

What is a good way to find the type of a more complex python object when trying to write statically typed python?

For example, I think I've got the type annotation of x correct here:

from itertools import combinations
from typing import Union, Iterator
x: Union[Iterator[tuple[int]]] =  combinations([1,2,3], 2)

However I'd love to have figured out the type by doing something simple like this:

print(type(itertools.combinations))
<class 'itertools.combinations'>

But this gives the wrong result, i.e. <class 'itertools.combinations'> is not Union[Iterator[tuple[int]]] which I think is the correct type annotation here for x.

In addition, PyCharm tells me that Union[Iterator[tuple[int]]] is the correct type but when I click the documentation link it just gives me this which is the standard python docs for itertools and I can't see any type annotations there. So wondering if there's a way to access what PyCharm is doing under the hood here...

osint_alex
  • 952
  • 3
  • 16
  • 3
    `reveal_type` from `mypy` might help https://stackoverflow.com/questions/44625422/how-to-use-reveal-type-in-mypy – MegaIng Jan 05 '22 at 22:27
  • 2
    A union of one type doesn't make sense. – jonrsharpe Jan 05 '22 at 22:28
  • 1
    "PyCharm tells me that `Union[Iterator[tuple[int]]]` is the correct type" I think that PyCharm is telling you that there's no conflict, but that doesn't mean it's the actual correct type (which explains why your `Union` is in there for no apparent reason? Unless you meant to imply `Union[X, None]`?) Note that there's a difference in finding an answer and checking an answer - you're looking for something that finds the answer, PyCharm is checking your answer. – Grismar Jan 05 '22 at 22:31
  • 1
    The correct annotation should be `Iterator[tuple[int, int]]`. – user2357112 Jan 05 '22 at 22:31
  • Thanks all, Union doesn't make sense see what's going on now thanks to @Grismar – osint_alex Jan 05 '22 at 22:32
  • 2
    `combinations` *is* a type; it's not a function, but a class that implements the iterator protocol by yield one combination at a time. `Union[...]` isn't a type at all; it's a type *hint* that describes the values that `x` is allowed to take. – chepner Jan 05 '22 at 22:43

1 Answers1

1

"PyCharm tells me that Union[Iterator[tuple[int]]] is the correct type" I think that PyCharm is telling you that there's no conflict, but that doesn't mean it's the actual correct type, which explains why it allowed Union in there. Unless you meant to imply Union[X, None], but you'd want Optional for that.

Note that there's a difference in finding an answer and checking an answer - you're looking for something that finds the answer, PyCharm is checking your answer. It's like math, if you have the answer, it's easy to fill in a formula and check that it works out, but given the formula alone, complicated work is required to figure out the answer - and it's possible there are multiple correct answers.

This applies more broadly to print(type(itertools.combinations)) as well.

In your case, the correct return type to expect is Iterator[tuple[int]], but if you called combinations(['a','b','c'], 2), it would be Iterator[tuple[str]] - so the return type needs to be parameterised with the types you're calling the function with, making things even more complicated.

In short, there's no such thing as you're looking for, although there are some third party tools that may get you close, like reveal_type from mypy as user @MegaIng suggested. (I have no direct experience with it, but it looks worth checking out for some use cases)

Grismar
  • 27,561
  • 4
  • 31
  • 54