advanced programming techniques this decorator requires that every argument and the return value must be annotated with the expected type it checks that the function' arguments and return type are all annotated with their types when the function it is passed is createdand at runtime it checks that the types of the actual arguments match those expected the inspect module provides powerful introspection services for objects herewe have made use of only small part of the argument specification object it returnsto get the names of each positional and keyword argument--in the correct order in the case of the positional arguments these names are then used in conjunction with the annotations dictionary to ensure that every parameter and the return value are annotated the wrapper function created inside the decorator begins by iterating over every name-argument pair of the given positional and keyword arguments since zip(returns an iterator and dictionary items(returns dictionary view we cannot concatenate them directlyso first we convert them both to lists if any actual argument has different type from its corresponding annotation the assertion will failotherwisethe actual function is called and the type of the value returned is checkedand if it is of the right typeit is returned at the end of the strictly_typed(functionwe return the wrapped function as usual notice that the checking is done only in debug mode (which is python' default mode--controlled by the - command-line option and the pythonoptimize environment variableif we decorate the is_unicode_punctuation(function with the @strictly_typed decoratorand try the same examples as before using the decorated versionthe annotations are acted uponis_unicode_punctuation("zebr\ "is_unicode_punctuation( ="!@#?"is_unicode_punctuation(("!""@")returnsfalse returnstrue raises assertionerror now the argument types are checkedso in the last case an assertionerror is raised because tuple is not string or subclass of str now we will look at completely different use of annotations here' small function that has the same functionality as the built-in range(functionexcept that it always returns floatsdef range_of_floats(*args-"author=reginald perrin"return (float(xfor in range(*args)no use is made of the annotation by the function itselfbut it is easy to envisage tool that imported all of project' modules and produced list of function names and author namesextracting each function' name from its __name__ attributeand the author names from the value of the __annotations__ dictionary' "returnitem