When we consider the implications of what's happening here, they're pretty impressive. Once the function returns, the wrapper checks for a return value adapter if it finds one, it applies it to the return value before finally returning it. Once the function is wrapped, wrapper also looks for adapters in the function's parameter annotations and applies them before passing the arguments to the real function. This wrapper only accepts keyword arguments, which means that even, if the original function could accept positional arguments, they have to be specified by name. So, the adapted decorator encloses the function in a wrapper. from functools import wrapsĪdapt = func._annotations_.get('result') Annotations as input to function decoratorsĪnnotations combine well with decorators because annotation values make a good way to provide input to a decorator, and decorator-generated wrappers are a good place to put code that gives meaning to annotations. The decorator is for protecting corner cases where things are ambiguous. Normally, this isn’t required as most tools that use annotations have a way of recognizing the ones meant for them. Accessing Function AnnotationsĪll the annotations are stored in a dictionary called _annotations_, which itself is an attribute of the function − > def func(x:'annotating x', y: 'annotating y', z: int) -> float: print(x + y + z) So, we see the annotations have no effect on the execution of the function func(). In both cases, func() does the right thing and annotations are simply ignored. Output > func(2,3,-4)Ībove we call func() twice, once with int arguments and once with string arguments. Here the ‘->’ syntax for annotating the return value. The return value is annotated with the type float. The first argument x is annotated with string ‘annotating x’, second argument y is annotated with the string ‘annotating y’, and the third argument z is annotated with type int. In the above example, function func() takes three parameters called x,y and z, finally prints their sum. > def func(x:'annotating x', y: 'annotating y', z: int) -> float: print(x + y + z) It only provides nice syntactic support for associating metadata as well as an easy way to access it. It’s important to understand that python doesn’t provide any semantics with annotations. def foo(x1, y1: expression), (x2: expression, y2: expression)=(None, None)): It is not required to annotate all the parameters of a nested parameter. In the case of nested parameters, annotations always follow the name of the parameters and not till the last parenthesis. Whereas the annotations for excess parameters are as − def foo(**args: expression, **kwargs: expression): The annotations for parameters take the following form − def foo(x: expression, y: expression = 20): All this work left to the third-party libraries. The PEP-3107 makes no attempt to introduce any kind of standard semantics, even for the built-in types. Let’s understand some basics of function annotations −įunction annotations are completely optional both for parameters and return value.įunction annotations provide a way of associating various parts of a function with arbitrary python expressions at compile time. The primary purpose was to have a standard way to link metadata to function parameters and return value. Since python 3, function annotations have been officially added to python (PEP-3107). Function annotations introduced in Python 3.0 adds a feature that allows you to add arbitrary metadata to function parameters and return value.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |