Let's take an example of a function which receives two arguments and returns a value indicating their sum:
def two_sum(a, b):
return a + b
By looking at this code, one can not safely and without doubt indicate the type of the arguments for function two_sum
. It works both when supplied with int
values:
print(two_sum(2, 1)) # result: 3
and with strings:
print(two_sum("a", "b")) # result: "ab"
and with other values, such as list
s, tuple
s et cetera.
Due to this dynamic nature of python types, where many are applicable for a given operation, any type checker would not be able to reasonably assert whether a call for this function should be allowed or not.
To assist our type checker we can now provide type hints for it in the Function definition indicating the type that we allow.
To indicate that we only want to allow int
types we can change our function definition to look like:
def two_sum(a: int, b: int):
return a + b
Annotations follow the argument name and are separated by a :
character.
Similarly, to indicate only str
types are allowed, we'd change our function to specify it:
def two_sum(a: str, b: str):
return a + b
Apart from specifying the type of the arguments, one could also indicate the return value of a function call. This is done by adding the ->
character followed by the type after the closing parenthesis in the argument list but before the :
at the end of the function declaration:
def two_sum(a: int, b: int) -> int:
return a + b
Now we've indicated that the return value when calling two_sum
should be of type int
. Similarly we can define appropriate values for str
, float
, list
, set
and others.
Although type hints are mostly used by type checkers and IDEs, sometimes you may need to retrieve them. This can be done using the __annotations__
special attribute:
two_sum.__annotations__
# {'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}