Python function annotations

Function annotation is a new feature introduced in version 3.0, which supports adding annotations to function parameters and return values.


Annotations can be used to document helpful information and can also be used to label types.
Annotations have no additional semantics except that they can be obtained using the __annotations__ attribute. Leave enforcement control to the framework, metaclasses and decorators, while Python sits on the sidelines.


definition


1) Parameter annotation
variable name[:comment] [=default value] is
strictly in the order of first comment and default value, and both are optional. Both comments and defaults must be Python expressions, which are evaluated when the function definition is executed.

def foo(a: expression, b: expression = 5):
    ...

def foo(*args: expression, **kwargs: expression):
    ...

2) return value annotation
def function name (parameter list) -> comment :
    ...
which is optional and must be a Python expression. It is evaluated when the function definition is executed.


Attributes


1) The annotation dictionary can be obtained through the __annotations__ attribute. If there is a return value annotation, the key of return is in the dictionary, so the parameter cannot be named with return.

def foo(a: 'aa', b: 5 + 6, c: int) -> str:
    pass
foo.__annotations__

{'a': 'aa', 'b': 11, 'c': <class 'int '>, 'return': <class 'str'>}


application


Use function annotations to check the types of arguments and return values, making up for the lack of Python's weak typing

#!/usr/bin/env python3
# coding=utf-8


def check_params(func):
    def inner(*args, **kwargs):
        rules = func.__annotations__ # Get annotations for parameters and return values

        for name, value in kwargs.items(): # Check the type of keyword arguments passed in
            if not isinstance(value, rules[name]):
                raise RuntimeError('%s want %s, but %s' % (name, rules[name], type(value)))

        back = func(*args, **kwargs)

        if 'return' in rules and not isinstance(back, rules['return']): # check return type
            raise RuntimeError('return want %s, but %s' % (rules['return'], type(back)))

        return back

    return inner


# test to check the parameter type
@check_params
def intro(name: str, age: int, high: float = 160):
    print('%s is %d years old, %f centimeters high.' % (name, age, high))


# test to check return type
@check_params
def back(num) -> int:
    return num


# Test for universality of instance methods
class Mobile(object):

    def __init__(self, mobile):
        self.mobile = mobile

    def __str__(self):
        return self.mobile


class Factory(object):

    @check_params
    def intro(self, name: str, mobile: Mobile):
        print('%s publish %s' % (name, mobile))


if __name__ == '__main__':
    intro(name='Ming', age=23)
    # intro(name=222, age='3333')
    back(5)
    # back(5.6)
    mobile = Mobile('mix')
    xm = Factory()
    xm.intro(name='xiaomi', mobile=mobile)
    xm.intro(name='xiaomi', mobile='mix')



Remark


Lambda expressions do not support function annotations.

Function annotations can be used for type checking and overloading functions.


If there is any inappropriateness in the text, please forgive and point out, thank you.


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325561851&siteId=291194637