(expression for item in iterable)
(expression for item in iterable if condition)The easiest way to execute an expression is to use the built-in eval() function.
x = eval("(2 ** 31) - 1") # x == 2147483647This is fine for user-entered expressions, but what if we need to create a function dynamically? For that we can use the built-in exec() function.
In some cases it is convenient to provide the entire global context to exec(). This can be done by passing the dictionary returned by the globals() function. One disadvantage of this approach is that any objects created in the exec() call would be added to the global dictionary. A solution is to copy the global context into a dictionary, for example, context = globals().copy().
We can also pass the local context, for example, by passing locals() as a third argument—this makes objects in the local scope accessible to the code executed by exec().
Table 8.1 Dynamic Programming and Introspection Functions
Here is a slightly cleaner version of the @positive_result decorator. The wrapper itself is wrapped using the functools module’s @functools.wraps decorator, which ensures that the wrapper() function has the name and docstring of the original function.
We can call a function with the parameters we want and that returns a decorator which can then decorate the function that follows it.
It is a logging function that records the name, arguments, and result of any function it is used to decorate. For example:
Here’s the general syntax:
def functionName(par1 : exp1, par2 : exp2, ..., parN : expN) -> rexp:
suiteIf annotations are present they are added to the function’s __annotations__ dictionary; if they are not present this dictionary is empty.
Here is an example of an annotated function that is in the Util module:
If we want to give meaning to annotations, for example, to provide type checking, one approach is to decorate the functions we want the meaning to apply to with a suitable decorator. Here is a very basic type-checking decorator:















