This article mainly introduces the Python function Programming Guide (2): Starting from the function, this article explains how to define a function, use function assignment, closure, as a parameter, and so on, for more information, see
2. Start with the function
2.1. Define a function
A Summation function is defined as follows:
The Code is as follows:
Def add (x, y ):
Return x + y
For more information about the syntax of parameters and returned values, see other documents.
Lambda can be used to define simple single-row anonymous functions. Lambda Syntax:
The Code is as follows:
Lambda args: expression
The syntax of the parameter (args) is the same as that of a common function. At the same time, the value of the expression is the return value of an anonymous function call, while the lambda expression returns this anonymous function. If we give an anonymous function a name like this:
The Code is as follows:
Lambda_add = lambda x, y: x + y
This is exactly the same as the summation function defined by def. You can call it using lambda_add as the function name. However, lambda is provided to write anonymous functions that are occasionally, simple, and foreseeable to be modified. Although this style looks cool, it is not a good idea, especially when it needs to be expanded one day, it can no longer be written using an expression. If you need to name a function at the beginning, you should always use the def keyword.
2.2. assign values using functions
As a matter of fact, you have already seen it. In the previous section, we assigned the lambda expression to add. Similarly, a function defined by def can be assigned a value, which is equivalent to an alias for the function and can be used to call the function:
The Code is as follows:
Add_a_number_to_another_one_by_using_plus_operator = add
Print add_a_number_to_another_one_by_using_plus_operator (1, 2)
Since a function can be referenced by a variable, It is very common to use the function as a parameter and return value.
2.3. Closure
A closure is a special type of function. If a function is defined in the scope of another function and the function references the local variables of the external function, this function is a closure. The following code defines a closure:
The Code is as follows:
Def f ():
N = 1
Def inner ():
Print n
Inner ()
N = 'X'
Inner ()
The inner of the function is defined in the scope of f, and the local variable n in f is used in the inner, which forms a closure. The closure is bound to external variables, so the result of calling function f is to print 1 and 'x '. This is similar to the relationship between common module functions and global variables defined in the module: modifying external variables can affect values in the internal scope, while defining variables with the same name in the internal scope will mask (hide) external variable.
To modify global variables in a function, you can use the global keyword to modify the variable name. In Python 2. x, there are no keywords to support modifying external variables in the closure. in Python 3. x, the keyword nonlocal can do this:
The Code is as follows:
# Python 3.x supports 'nonlocal'
Def f ():
N = 1
Def inner ():
Nonlocal n
N = 'X'
Print (n)
Inner ()
Print (n)
The result of calling this function is to print 1 and 'x'. If you have a Python 3. x interpreter, you can try to run it.
Because the variables defined by the function in vitro are used, it seems that the closure violates the functional style rules that do not depend on the external state. However, because the closure is bound to the local variables of the external function, once the external function scope is left, these local variables will no longer be accessible from the External. In addition, the closure has an important feature, A new closure is constructed every time it is executed to the closure definition, so that the variables bound to the old closure do not change with the second call to the external function. Therefore, closures are not actually affected by external States and fully comply with functional style requirements. (Here is a special case. In Python 3. x, if two closures are defined in the same scope, they can affect each other because they can modify external variables .)
Although a closure can exert its real power only when it is used as a parameter and a return value, the support of the closure still greatly improves productivity.
2.4. As a parameter
If you are familiar with the OOP template method mode, you can quickly learn to pass functions as parameters. The two are basically the same, but here we pass the function itself rather than the object that implements an interface.
Let's warm-up the previously defined summation function add:
The Code is as follows:
Print add ('tree of triangles ', 'Arctic ')
Unlike the addition operator, you must be surprised that the answer is 'trigonometric function '. This is a built-in egg... bazinga!
Let's get down to the truth. Our customers have a list from 0 to 4:
The Code is as follows:
Lst = range (5) # [0, 1, 2, 3, 4]
Although we have given him an operator in the previous section, he is still worried about how to calculate the sum of all elements in this list. Of course, this task is very easy for us:
The Code is as follows:
Amount = 0
For num in lst:
Amount = add (amount, num)
This is a typical script-style code. There is no problem at all. You can certainly get the correct result. Now, let's try to refactor it with a functional style.
First of all, we can foresee that the summation action is very common. If we abstract this action into a separate function, when we need to sum up another list, you don't have to write this routine again:
The Code is as follows:
Def sum _ (lst ):
Amount = 0
For num in lst:
Amount = add (amount, num)
Return amount
Print sum _ (lst)
Continue. The sum _ function defines a process as follows:
1. Add the initial value to the first element of the list;
2. Add the result of the last addition to the next element of the list;
3. Repeat Step 2 until there are no more elements in the list;
4. Return the result of the last addition.
If the product is required now, we can write a similar process-simply replace the sum with the multiplication:
The Code is as follows:
Def multiply (lst ):
Product = 1
For num in lst:
Product = product * num
Return product
Except for changing the initial value to 1 and the function add to the multiplication operator, all other code is redundant. Why don't we abstract this process and pass in addition, multiplication, or other functions as parameters?
The Code is as follows:
Def reduce _ (function, lst, initial ):
Result = initial
For num in lst:
Result = function (result, num)
Return result
Print reduce _ (add, lst, 0)
To calculate the product, do the following:
The Code is as follows:
Print reduce _ (lambda x, y: x * y, lst, 1)
So what should we do if we want to use reduce _ to find the maximum value in the list? Please think about it yourself :)
Although there is a design pattern such as the template method, such complexity often makes people prefer to write loops everywhere. Using functions as parameters completely avoids the complexity of the template method.
Python has a built-in reduce function that fully implements and extends the reduce _ function. Later in this article, we will introduce some useful built-in functions. Note that our purpose is to avoid loops. Replacing loops with functions is the most obvious feature of the functional style that distinguishes it from the directive style.
* A function-based language built on C language like Python provides the ability to write loop code. Although built-in functions provide function-based programming interfaces, but it is usually implemented in a loop. Similarly, if you find that built-in functions cannot meet your cycle needs, you may also encapsulate them and provide an interface.
2.5. Return Value
Returning a function usually needs to be used with a closure (that is, returning a closure) to exert its power. Let's first look at the definition of a function:
The Code is as follows:
Def map _ (function, lst ):
Result = []
For item in lst:
Result. append (function (item ))
Return result
Function map _ encapsulates the most common iteration: calls a function for each element in the list. Map _ requires a function parameter and saves the result of each call to a list to return. This is a directive practice. When you know the list resolution (list comprehension), it will be better implemented.
Here we will skip the poor implementation of map _ and focus only on its functions. For the lst in the previous section, you may find that the final result of the product is always 0, because the lst contains 0. To make the results look large enough, we use map _ to add 1 to each element in the lst:
The Code is as follows:
Lst = map _ (lambda x: add (1, x), lst)
Print reduce _ (lambda x, y: x * y, lst, 1)
The answer is 120, which is far from big enough. Again:
The Code is as follows:
Lst = map _ (lambda x: add (10, x), lst)
Print reduce _ (lambda x, y: x * y, lst, 1)
Actually, I didn't really think the answer would be 360360. I swear I didn't accept any benefit from Zhou Hongyi.
Now let's look at the two lambda expressions we have written: the similarity is over 90%, which can be described as plagiarism. But the question is not plagiarism, but whether many characters are written? If there is a function that generates an addition function based on the specified left operand, it is used as follows:
The Code is as follows:
Lst = map _ (add_to (10), lst) # add_to (10) returns a function that accepts a parameter and adds 10.
It should be quite comfortable to write. The following is the implementation of the add_to function:
The Code is as follows:
Def add_to (n ):
Return lambda x: add (n, x)
By specifying several parameters for an existing function to generate a new function, this function can implement all functions of the original function by passing in the remaining unspecified parameters, this is called a partial function. Python's built-in functools module provides a function partial that can generate partial functions for any function:
The Code is as follows:
Functools. partial (func [, * args] [, ** keywords])
You need to specify the function to generate the partial function, and specify several parameters or named parameters. Then, partial returns this partial function. However, partial returns not a function strictly, it is an object that can be called directly like a function. Of course, this will not affect its function.
Another special example is the decorator. The decorator is used to enhance or even change the functions of the original function. I have written a document about the decorator at http://www.jb51.net/article/59867.htm.
* In other functional languages (such as Scala), you can use the Currying technology to achieve elegance. Curialization converts a function that accepts multiple parameters into a function that accepts a single parameter (the first parameter of the initial function, and return the technology of the new function that accepts the remaining parameters and returns results. The following pseudo code is shown:
The Code is as follows:
# Not real code
Def add (x) (y): # kerihua
Return x + y
Lst = map _ (add (10), lst)
The add function is colized so that add accepts the first parameter x and returns a function that accepts the second parameter y, calling this function is exactly the same as add_to (returns x + y) in the previous article, and you do not need to define add_to. Does it seem more refreshing? Unfortunately, Python does not support colitization.
2.6. Introduction to some built-in functions
Reduce (function, iterable [, initializer])
The main function of this function is the same as the reduce _ defined by us. Two additional points are required:
Its second parameter can be any iteratable object (the object implementing the _ iter _ () method );
If the third parameter is not specified, the first two elements of iterable are used as the parameters when the function is called for the first time.
The built-in functions listed below are combined by reduce and some common functions:
The Code is as follows:
All (iterable) = reduce (lambda x, y: bool (x and y), iterable)
Any (iterable) = reduce (lambda x, y: bool (x or y), iterable)
Max (iterable [, args...] [, key]) = reduce (lambda x, y: x if key (x)> key (y) else y, iterable_and_args)
Min (iterable [, args...] [, key]) = reduce (lambda x, y: x if key (x) <key (y) else y, iterable_and_args)
Sum (iterable [, start]) = reduce (lambda x, y: x + y, iterable, start)
Map (function, iterable ,...)
The main function of this function is the same as the map _ defined by us. You need to add:
Map can also accept multiple iterable parameters. When calling function n, iterable1 [n], iterable2 [n],... is used as the parameter.
Filter (function, iterable)
This function filters out all elements in iterable that return True or bool (Return Value) as True when the function is called with the element itself as a parameter and returns the result in a list, it is the same as the my_filter function in the first part of the series.
Zip (iterable1, iterable2 ,...)
This function returns a list. Each element is a tuples that contain (iterable1 [n], iterable2 [n],...).
Example: zip ([1, 2], [3, 4]) --> [(1, 3), (2, 4)]
If the length of the parameter is inconsistent, it ends at the end of the shortest sequence. If no parameter is provided, an empty list is returned.
You can also use functools. partial () mentioned in section 2.5 to create common partial functions for these built-in functions.
In addition to these built-in functions, there is a module named functional in pypi that provides more interesting functions. However, because there are not many use cases and additional installation is required, we will not introduce them in this article. But I still recommend that you download the source code of this module's pure Python implementation to broaden your mind. The functions inside are very short, the source file is a total of less than 300 lines, the address here: http://pypi.python.org/pypi/functional
This article ends :)