Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the proper Python type hint, for instance, the signature of the built-in function map()

Description

In Python 3.5 or above, type hints are supported (see here for more information). However, the proper usage for common types are not well documented.

For instance, from the official site, I could gather the following (proper) usages:

String

# The function signature of greeting is: Callable[[str], str]
def greeting(name: str) -> str:
    return 'Hello ' + name

Integer

# The function signature of add is: Callable[[int, int], int]
def add(a: int, b: int) -> int:
    return a + b

Floating Point Number

# The default value of x is 1.0
def reciprocal(x: float = 1.0) -> float:
    from math import nan
    if x == 0:
        return nan
    return 1 / x

List

from typing import List, TypeVar

T = TypeVar('T')

def repeat(x: T, n: int) -> List[T]:
    return [x] * n

Tuple

from typing import Tuple, TypeVar

T = TypeVar('T')

def double(x: T) -> Tuple[T, T]:
    return (x, x)

Questions

My questions are:

1. What is the return type of map?

from typing import Iterable

# Is this correct?
x: Iterable[float] = map(int.__float__, [1, 2, 3])

I am not sure if this is the correct type hint for x above.

2. In a broader sense, what is the 'function signature' of map?

from typing import Callable, Iterable, TypeVar

T = TypeVar('T')
U = TypeVar('U')

# In the above usage, the type of the map function seems to be:
Function1 = Callable[[T], U]
typeOfMap = Callable[[Function1, Iterable[T]], Iterable[U]]

# Or in one line:
typeOfMap = Callable[[Callable[[T], U], Iterable[T]], Iterable[U]]

But in fact, the map function can accept multiple iterables. It is documented as:

map(function, iterable, ...)

It could be used like this:

# The result is: [['A'], ['B', 'B'], ['C', 'C', 'C']]
result = list(map(repeat, ['A', 'B', 'C'], [1, 2, 3]))

T1 = TypeVar('T1')
T2 = TypeVar('T2')
R = TypeVar('R')

# So, the type of map function in this usage seems to be:
Function2 = Callable[[T1, T2], R]
typeOfMap = Callable[[Function2, Iterable[T1], Iterable[T2]], Iterable[R]]

In general, I guess it should be something like below, but this is not the correct way to write it:

FunctionN = Callable[[T1, T2, ..., Tn], R]
typeOfMap = Callable[[FunctionN, Iterable[T1], Iterable[T2], ..., Iterable[Tn]], Iterable[R]]

So, what is the correct way to write it?

3. In general, where can I find the correct type hint of a Python function / method, including the built-in ones, those in the core libraries?

I need them mainly for learning purpose.

4. Is there any way to output the type inference result computed by the compiler / interpreter, as in Haskell or Erlang?

I know Haskell and Erlang are functional programming languages and variables are immutable, so it would be much easier to make this possible, but just in case if Python also has similar functionalities, I would like to know.

5. Is there any way to check that my type hint is correct?

Or at least let it show me some warning / error at compile time / runtime so that I am aware that something is wrong.

References

  • typing — Support for type hints — Python 3.x.x documentation
  • Built-in Functions — Python 3.x.x documentation

At the time of this writing, the latest stable version is 3.8.0.

like image 240
Siu Ching Pong -Asuka Kenji- Avatar asked Oct 19 '19 16:10

Siu Ching Pong -Asuka Kenji-


People also ask

How do I get the hint of a function in Python?

From the Python typing documentation, you may use typing. get_type_hints() . Return a dictionary containing type hints for a function, method, module or class object. This is often the same as obj.

How do you write a class hint in Python?

In a type hint, if we specify a type (class), then we mark the variable as containing an instance of that type. To specify that a variable instead contains a type, we need to use type[Cls] (or the old syntax typing. Type ).

What is typing mapping in Python?

typing.Mapping is an object which defines the __getitem__,__len__,__iter__ magic methods. typing. MutableMapping is an object which defines same as Mapping but with __setitem__,__delitem__ magic methods as well. typing.Mapping et al. are based on the abc types in this table.

Does Python have type hints?

Python's type hints provide you with optional static typing to leverage the best of both static and dynamic typing. Besides the str type, you can use other built-in types such as int , float , bool , and bytes for type hintings. To check the syntax for type hints, you need to use a static type checker tool.

How to get the signature of a function in Python?

This can be achieved in two ways – We can get function Signature with the help of signature () Function. It takes callable as a parameter and returns the annotation. It raises a value Error if no signature is provided. If the Invalid type object is given then it throws a Type Error. To do this the functions in Python certain attributes.

What are type hints in Python?

Type hints are available for all the packages in the Python standard library. However, if you are using third-party packages you’ve already seen that the situation can be different. The following example uses the Parse package to do simple text parsing. To follow along you should first install Parse: Parse can be used to recognize simple patterns.

How to check the type of a function in Python?

For that purpose, use the typing.Callable type (see here ): The first argument to Callable is a list of types for the arguments of the function, while the second argument is the return type. Of course, python itself does not check types at all. For this, you should use additional tools such as mypy Show activity on this post.

What are the __code__ attributes in Python?

The __code__ attributes also have certain attributes that will help us in performing our tasks. We will be using the co_varnames attribute that returns the tuple of names of arguments and local variables and co_argcount that returns the number of arguments (not including keyword-only arguments, * or ** args).


1 Answers

1. What is the return type of map?

map’s return value is currently typed as an Iterator[T]. Since iterators are iterables, your annotation of x: Iterable[float] = map(int.__float__, [1, 2, 3]) is valid. (Also, just write map(float, [1, 2, 3]).)

2. In a broader sense, what is the 'function signature' of map?

It’s currently impossible to represent, which is why typeshed has overloads for up to 6 generic parameters. (one related issue)

3. In general, where can I find the correct type hint of a Python function / method, including the built-in ones, those in the core libraries?

I need them mainly for learning purpose.

Python’s typeshed repository. Note that for non-learning purposes – practice – you should generally either let the type be inferred or use whatever type makes sense rather than the most exact type possible.

You can also use reveal_type – see below.

4. Is there any way to output the type inference result computed by the compiler / interpreter, as in Haskell or Erlang?

I know Haskell and Erlang are functional programming languages and variables are immutable, so it would be much easier to make this possible, but just in case if Python also has similar functionalities, I would like to know.

This is up to your typechecker. Mypy has reveal_type.

x = map(float, [1, 2, 3])
reveal_type(x)  # note: Revealed type is 'typing.Iterator[builtins.float*]'

5. Is there any way to check that my type hint is correct?

Or at least let it show me some warning / error at compile time / runtime so that I am aware that something is wrong.

Statically, that’s what typechecking is. (For example, Mypy would have told you if your x hint were wrong.) It can’t catch everything, especially in a language as dynamic as Python, but that’s the nature of programming.

There are a few projects that do some level of runtime assertions based on type annotations, but none I’ve used or would really bother with.

like image 184
Ry- Avatar answered Sep 30 '22 10:09

Ry-