Overview
In this article, we will discuss an important concept of functional programming, "Functions are first-class citizens", and introduce the concepts of Currying, Partial Applied Function, and Multivariate Functions by the way.
Multi Function
The first one we want to introduce is the concept of multivariate functions. In fact, it is useless to say more. A multivariate function is a function with more than one parameter. Its "pipe diagram" can be summarized as follows:
This is another extension to the water pipe. From then on, we can merge the two branches.
Function as parameter
The following, of course, is our first statement of first-class citizens, that is, we can take a function as a parameter into another function. As shown below, at this time we got the expansion of the water pipe function. A water pipe can exist as a component of another water pipe.
The biggest advantage of this operation is that we can abstract the function (operation) itself. For example, the compose
command we implemented in the previous chapter is a very typical example. They are abstract thinking about the unary function itself.
Let's take an example here, that is, we need to calculate the Euclidean distance between each two-dimensional point in the list according to the order of a list, which can be written as the following function:
import math
def euclidean_distance_between_two_ls(ls1, ls2):
euclidean_distance_between_two_point = lambda x, y: math.sqrt((x[0] - y[0]) ** 2 + (x[1] - y[1]) ** 2)
return [euclidean_distance_between_two_point(i, j) for i, j in zip(ls1, ls2)]
After completing this example, we will soon find that this function can not only calculate Euclidean distance, but can be abstracted as a function that can be calculated for all distance formulas:
def distance_between_two_ls(ls1, ls2, distance_func):
return [distance_func(i, j) for i, j in zip(ls1, ls2)]
If you are a data worker, you should be alert to discover that this kind of thinking can also be used to easily replace "correlation", "neuron function", "stemming method" and other fields.
Function as return value
The following is our next expansion of the water pipe, which is also the next embodiment of the first-class citizen of the function, that is, the function as the return value, the approximate water pipe diagram is as follows:
The benefits of this, we can still continue the above statement, we have made a higher level of abstraction of functions and operations. Of course, this is eliminated. On a practical level, doing so can generate two Tips, which are calculated in advance and calculated in delay.
Let's consider the following example:
one = lambda : 1
In this example, we need to rely on one()
to get the actual value 1
. This is an example of the smallest delay calculation. Of course, in the following example, we will use this to realize the concept of a set of natural numbers based on Peano's axiom. Of course, in more cases, the delay calculation is reflected in that we only use some parameters to generate a water pipe instead of a specific value, and finally participate in the calculation by calling the water pipe. compose
in the previous chapter. We just assembled the water pipe into a new water pipe instead of calling it directly.
Of course, we can also implement the concept of "calculating in advance" or saving state. For example, the following example:
def f(x, y):
z = x ** 2 + x + 1
return y * z
If we often need to use x = 1
, obviously, the method of making a return function is more effective. We can associate this with the object-oriented concept of how to store and update the properties of an object. The following strategy is actually the most basic method save the state x
is equal to a certain value (analogously, we save the age of a student named "Li Hua". Note that we don’t need it. The concepts of instantiation, methods, and properties are gone, we only have functions, functions, and functions).
def f(x):
def helper(y):
z = x ** 2 + x + 1
return y * z
return helper
This process is also called (Currying), but the definition of Currying is very strict, that is, only one parameter is passed in each time, so that we can always reuse the situation of x = 1
f1 = f(1)
# 调用
f1(2)
f1(3)
If we simply do this, we can use functools.partial
to rewrite the multivariate function that has been maintained.
from functools import partial
def f(x, y):
z = x ** 2 + x + 1
return y * z
f1 = partial(f, 1)
f1(2)
f1(3)
But as a performance tuning, it seems that the way of writing functions in functions has another advantage, which is the "pre-calculation" mentioned earlier. Such as the example above, when the apparent x
into the post, z
can be calculated immediately, without waiting for y
passed. And, we found that every time f1
is z
is calculated once. Thus, we can see another feature as a return value function. The following function shows all the tricks and benefits of the function as the return value. This kind of function is also called Partial Applied Function or Partial Function for short (note the difference with the partial function defined by mathematics in 001).
def f(x): # x储存了某种我们需要的状态
## 所有可以提前计算的放在这里
z = x ** 2 + x + 1
def helper(y):
## 所有延迟计算的放在这里
return y * z
return helper
Summarize
Performance as a function of first-class citizens:
- We only have two concepts as the function of the water pipe and the water entering the water pipe;
- Function can be passed into another function as a parameter;
- Function can be used as the return value of another function;
We call a function with at least one of the features 2 and 3 as higher-order functions. Some advantages of higher-order functions include:
- Only the concepts of functions and values are needed to save state. No need for more concepts such as instantiation, objects, variable variables, attributes, etc.;
- The calculation can be delayed to achieve the most basic concept of "laziness".
- It can be calculated in advance to achieve more efficient reuse of code blocks.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。