A function is defined and called using the terms:
1. Names of builtins functions.
💡How to fix it?
2. Modify values out of the function scope
💡Why do we need Python functions?
Python functions either (1) returns some value to the caller, or (2) have some side effects.
/* side effect */
void swap(int *x, int *y)
{
int *tmp;
tmp = x;
x = y;
y = tmp;
return;
}
/* return value */
int* createArray()
{
int res[10];
return &(res[0]);
}
3. Chained call of function
🎨 Time to draw!
To visualize: use pythontutor!
Generators are also functions. The object is generator-iterator. The generator function differs from normal functions in that the frame is SUSPENDED after executing yield. It is resumed with certain behaviors.
The yield statement can do more than sending out results to generators.
In Python, everything is an object. So when we call f(x=1), we pass an int object to x. Similarly, functions in Python are also objects. We can also pass functions as parameters to a function and receive another function as the output. Therefore, we abstract the computational processes. For example, consider implementing 3 machine learning algorithms to analyze data, we can store the detailed algorithm code in one file but in our main.py, we can use a common function to call the algorithms.
We use decorators to simplify higher-order functions. One important usage of decorators is to "add" extra behaviors of other functions. Let's go back to the fibonacci function we defined. The reason it takes long time to get returns for fibonacci(35) is the recursive computation of fibonacci(1) through fibonacci(34). Suppose we can save the already-computed results instead of call back itself. The computation time can be greatly shortened. The question is, how can we implement such a method?
Remember: decorator is applied to function at definition, not at runtime. So retroactively modify the definition of the decorator function will not change the already defined-decorated function.
When we want to access the attributes of the functions, a useful decorator is @functools.wraps.
Remember: we need to "prime" a coroutine so that we can send values to it? People thinking of it as tedious wrap the generator function in a decorator.
Learn more about decorators here.
We will talk about a more complicated example here.
Thinking about adding parameters to the decorator? Check this out.
When a function refers to itself inside the body function ...
Recursion is very useful. For example, we can implement the auto differentiation method later.