What are function annotations in Python

Today we will discuss function annotations in Python. Function annotation links arbitrary metadata to the function arguments and its return value.
PEP3107 has introduced the syntax of function annotations as a feature in Python 3.0.

What are Function Annotations?

  • Function annotation is the standard way to access the metadata with the arguments and the return value of the function.
  • These are nothing but some random and optional Python expressions that get allied to different parts of the function.
  • They get evaluated only during the compile-time and have no significance during the run-time of the code.
  • They do not have any significance or meaning associated with them until accessed by some third-party libraries.
  • They are used to type check the functions by declaring the type of the parameters and the return value for the functions.
  • The string-based annotations help us to improve the help messages.
  • Example of a function having annotations:
    def func(a: 'int') -> 'int':
        pass

    In the above code, we have a function func with a parameter named a. The data type of this parameter is marked through the annotation, int. Similarly, the data type for the return value is also marked as int.

The syntax for using function annotations in Python

A function can have three types of parameters: simple parameters, excess parameters and nested parameters. Below we are listing the syntax for annotating each type of parameters.

Annotations for simple parameters:

They are general parameters passed to a function. The argument name followed by a colon that is again followed by the annotation expression(can be a data type specification or some other expression) forms the syntax for annotating these parameters.

def func(x: 'float'=10.8, y: 'argument2'):

In the above code the argument, ‘x’ of the function func, has been annotated to float data type and the argument ‘y’ has a string-based annotation. The argument can also be assigned to a default value using a ‘=’ symbol followed by the default value. These default values are optional to the code.

Annotations for excess parameters:

There are two excess parameters, *args and **kwargs. The role of these parameters is to allow the user to enter variable-length input for the function. The annotations for these parameters are marked correspondingly to the simple parameters.

def func(*args: expression, **kwargs: expression):

Annotations for nested parameters:

For nested parameters, annotations are followed by the parameter name. In the case of nested parameters, it is not necessary to annotate all the parameters.

def func((a: expression, b: expression), (c, d: expression)):

Annotations for return values:

For the return value of a function, we can annotate it as:

def func(a: expression) -> 'int':

The annotations for the return value is written after the ‘->’ symbol.

Note: Lambda functions do not support function annotations.

How to access function annotations?

Function annotations are accessed using the ‘__annotations__’ attribute. This attribute is a mutable dictionary that stores the function annotations. In case of a function with no annotations, this becomes an empty mutable dictionary. Within this dictionary, the parameter names act as keys and are mapped to the annotation expression.
The ‘return’ key inside the dictionary maps to the return value of the function.

def fib(n:'float', b:'int')-> 'result': 
    pass
print(fib.__annotations__) 

Output:

{'b': 'int', 'n': 'float', 'return' : 'result'}

The function annotations can also be accessed by using some standard modules like ‘inspect’ and ‘pydoc’. The ‘help()’ method from ‘pydoc’ and ‘getfullargspec()’ method of ‘inspect’ module can access the annotations.

Uses and applications

  • Function annotations can provide static type checking when used with the external library, ‘mypy’.
  • They make the code more readable by specifying the type for input arguments as well as the return value of the function.
  • These annotations are also used in function overloading, foreign-language bridges, and database query mapping.

Leave a Reply

Your email address will not be published. Required fields are marked *