How I started to understand Python functional programming--python functional programming first involved

Source: Internet
Author: User
Tags define function function definition square root

Python-Functional programming

    1. At the beginning we will understand what functional programming is:
      Functions: function
      Functional type: Functional, a programming paradigm
      Functional programming Features: treat calculations as functions rather than directives, close to the calculation
      Pure functional Programming: No variables required, no side effects, simple testing, high-order functions, code simplicity

Functional programming features supported by Python:
Not purely functional programming: allowed variables
Supports higher order functions: Functions can also be passed in as variables
Support closures: the ability to return functions with closures
Limited support for anonymous functions

    1. Higher order functions
      A variable can point to a function, the function name is actually a variable pointing to the function, and the higher order function is actually the function that can receive the function to do the argument.
      Len ([=3])
      Demo: Receive ABS function
      Define a function, receive think, x,y,f three parameters, where x, Y is a normal parameter, Z is a function.
      def add (x,y,f)
      return f (x) +f (y)
      Take a function as a parameter

Then I should start writing a simple high-order function:
def add (x, Y, f):
return f (x) + f (Y)
If you pass in ABS as the value of the parameter F:
Add ( -5, 9, ABS)
According to the function definition, the code that the function executes is actually:
ABS ( -5) + ABS (9)
Because parameter x, Y, and F can all be passed in arbitrarily, if f passes into other functions, it can get different return values.
Learning tasks:

Using the Add (x,y,f) function, calculate:
Gs.png
Import Math
def add (x, Y, f):
X=abs (x)
Y=abs (y)
return f (x) + f (Y)
Print Add (9, MATH.SQRT)
Then I take the main high-order function to study separately, step by step .....
Yes, it is better to be able to complete the study task independently, of course, beyond their own ability to reference is also possible
1.map () function

Format: Map (f,list)
Map () is a Python built-in high-order function that receives a function f and a list, and then, by putting the function f on each element of the list in turn, gets a new list and returns.
For example, for list [1, 2, 3, 4, 5, 6, 7, 8, 9]
If you want to square each element of the list, you can use the map () function:
Map.png
Therefore, we only need to pass in the function f (x) =x*x, we can use the map () function to complete this calculation:
def f (x):
Return x*x
Print map (f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
Output Result:
[1, 4, 9, 10, 25, 36, 49, 64, 81]
Note: the map () function does not change the original list, but instead returns a new list.
With the map () function, you can convert a list to another list, just pass in the conversion function.
Because the list contains elements that can be of any type, map () can not only handle lists that contain only numeric values, but in fact it can handle lists of any type, as long as the incoming function f can handle the data type.
Learning tasks:

Assume that the user entered the English name is not standardized, not according to the first letter, followed by the letter lowercase rules, use the map () function, a list (including some nonstandard English name) into a list containing the canonical English name:
Input: [' Adam ', ' LISA ', ' Bart ']
output: [' Adam ', ' Lisa ', ' Bart ']
def format_name (s):
return S[0].upper () + s[1:].lower ()
Print map (for Mat_name, [' Adam ', ' LISA ', ' BarT ']
split into two parts s[0] and s[1:], then process the application upper and lower respectively, and finally return to the
2.reduce () function

Format: Reduce (f,list, initial value)
The reduce () function is also a high-order function built into Python. The reduce () function receives a parameter similar to map (), a function f, a list, but behaves differently from map (), and reduce () the incoming function f must receive two parameters, and reduce () calls function f repeatedly on each element of the list and returns the final result value.
For example, write an F function that receives x and Y, and returns the and of X and Y:
def f (x, Y):
return x + y
When you call reduce (f, [1, 3, 5, 7, 9]), the Reduce function calculates the following:
First two elements are computed: F (1, 3), and the result is 4;
Then the result and the 3rd element are calculated: F (4, 5), the result is 9;
Then the result and the 4th element are calculated: F (9, 7), the result is 16;
Then the result and the 5th element are calculated: F (16, 9), the result is 25;
Since there are no more elements, the calculation ends and the result 25 is returned.
The above calculation is actually a summation of all the elements of the list. Although Python has built-in sum function sum (), it is simple to sum with reduce ().
Reduce () can also receive a 3rd optional parameter as the initial value of the calculation. If you set the initial value to 100, the calculation:
Reduce (f, [1, 3, 5, 7, 9], 100)
The result will change to 125 because the first round calculation is:
Calculates the initial value and the first element: F (100, 1), and the result is 101.
Learning tasks:

Python has built-in sum function sum (), but there is no quadrature function, please use Recude () to calculate the product:
Input: [2, 4, 5, 7, 12]
Output: Results of 2*4*5*7*12
def prod (x, y):
Return X*y
Print reduce (prod, [2, 4, 5, 7, 12])
Results:
3300
3.filter () function

Format: filer (f,list)
the filter () function is another useful high-order function built into Python, and the filter () function receives a function f and a list, the function of which is to judge each element, returning TRUE or False , filter () automatically filters out non-conforming elements based on the result of the decision, returning a new list of eligible elements.
For example, to delete an even number from a list [1, 4, 6, 7, 9, 12, 17], leaving an odd number, first, to write an odd-numbered function:
def is_odd (x):
return x% 2 = = 1
Then, using filt ER () filter out even:
Filter (Is_odd, [1, 4, 6, 7, 9,, +])
Results: [1, 7, 9, +]
with filter (), you can accomplish many useful functions, such as deleting None or an empty string:
def is_not_empty (s):
return S and Len (S.strip ()) > 0
Filter (is_not_empty, [' Test ', None, ', ' str ', ', ' E ND '])
Result: [' Test ', ' str ', ' END ']
Note: S.strip (RM) Deletes the character of the RM sequence at the beginning and end of the S string.
When RM is empty, the default is to remove the white space character (including ' \ n ', ' \ R ', ' \ t ', '), as follows:
A = ' 123 '
A.strip ()
Result: ' 123 '
a= ' \t\t123\r\n '
A.strip ()
Result: ' 123 '
Learning task:

Filter () to 1~100 that the square root is an integer number, i.e. the result should be:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Import Math
def IS_SQR (x):
r = Int (math.sqrt (x))
Return r*r==x
Print filter (IS_SQR, Range (1, 101))
Results:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
4. Custom sort Functions

Format: Sorted (list,f)
The python built-in sorted () function can sort the list:

Sorted ([5, 9, +])
[5, 9, (+), +]
but sorted () is also a high Order function, which can receive a comparison function to implement a custom sort, the definition of the comparison function is to pass in two elements to be compared x, y, if X should be in front of y, return-1, if X should be ranked after Y, return 1. returns 0 if x and y are equal.
Therefore, if we are going to sort in reverse order, we just need to write a reversed_cmp function:
def reversed_cmp (x, y):
If x > y:
return-1
If x < y:
Return 1
return 0
In this way, calling sorted () and passing in reversed_cmp can be sorted in reverse order:
Sorted ([5,, 9,], reversed_cmp)
[9, 5]
sorted () can also sort strings, which are compared by default in ASCII size:
sorted ([' Bob ', ' about ', ' Zoo ', ' Credit '])
[ ' Credits ', ' Zoo ', ' about ', ' Bob ',
' zoo ' before ' about ' because the ' Z ' ASCII code is smaller than ' a '.
Learning tasks:

When sorting strings, it is sometimes more customary to ignore the case sort. Use the sorted () higher-order function to implement an algorithm that ignores case ordering.
Input: [' Bob ', ' about ', ' Zoo ', ' credits ']
output: [' about ', ' Bob ', ' credits ', ' Zoo ']
Hint: For comparison function cmp_ignore_case (S1, S2), to ignore the case comparison, you would first capitalize the two strings (or all lowercase) before comparing them.
def cmp_ignore_case (S1, S2):
U1 =s1.upper ()
U2 =s2.upper ()
If U1 < u2:
Return-1
If U1 ; U2:
return 1
return 0
Print sorted ([' Bob ', ' about ', ' Zoo ', ' credits '],cmp_ignore_case)
Output:
[' About ', ' Bob ', ' Credit ', ' Zoo ']
or:
def cmp_ignore_case (S1, S2):
U1 =s1.lower ()
U2 =s2.lower ()
If U1 < u 2:
return-1
If U1 > U2:
return 1
return 0
Print sorted ([' Bob ', ' about ', ' Zoo ', ' credits '],cmp_i gnore_case)
Output:
[' About ', ' Bob ', ' credits ', ' Zoo ']
5. Return function

Python's functions can not only return data types such as int, str, list, dict, but also return functions!
For example, to define a function f (), we let it return a function g, which can be written like this:
def f ():
print ' Call f () ... '
# define function G:
def g ():
print ' call g () ... '
# return function g:
Return g
Looking closely at the function definition above, we define a function g inside the function f. Since the function g is also an object, the functions of the name G is the variable that points to the function g, so the outermost function f can return the variable g, which is the function G itself.
Call the function f, and we'll get a function of the F return:

x = f () # call F ()
Call F () ...
The x # variable x is the function returned by F ():

X () # x points to the function, so you can call the
Call G () ... # calling X () is the code that executes the G () function definition
Note that the return function and return value are distinguished:
Def myabs ():
Return ABS # returns function
def MYABS2 (x):
return ABS (x) # Returns the result of the function call, the return value is a number
The return function can delay execution of some computations. For example, if you define a normal sum function:
def calc_sum (LST):
return sum (LST)
When the Calc_sum () function is called, the result is calculated and obtained immediately:
Calc_sum ([1, 2, 3, 4])
10
However, if you return a function, you can "defer calculation":
def calc_sum (LST):
Def lazy_sum ():
return sum (LST)
Return lazy_sum

The call to Calc_sum () does not calculate the result, but instead returns the function:

f = Calc_sum ([1, 2, 3, 4])
F

The result is calculated when a call is made to the returned function:

F ()
10
Since the function can be returned, we can decide in the subsequent code whether or not to invoke the function.
Learning tasks:

Write a function Calc_prod (LST) that receives a list, returns a function, and returns a function that calculates the product of the parameter.
Define a function that calculates the product, and then return the function.
def calc_prod (LST):
Def lazy_prod ():
def f (x, Y):
Return X*y
return reduce (f,lst,1)
Return Lazy_prod
f = Calc_prod ([1, 2, 3, 4])
Print F ()
Results:
24
6. Closures

functions defined inside a function are the same as externally defined functions, except that they cannot be accessed externally:
def g ():
print ' g () ... '
def f ():
print ' F () ... '
Return g
Move the definition of G into the function f to prevent other code from calling G:
def f ():
print ' F () ... '
def g ():
print ' g () ... '
Return g
However, the Calc_sum function defined in the previous section is examined:
def calc_sum (LST):
Def lazy_sum ():
return sum (LST)
Return lazy_sum
Note: It is not found to be able to move the lazy_sum outside the calc_sum because it references the calc_sum parameter lst.
Such an inner layer function refers to a variable of the outer function (parameter is also a variable), and then returns the case of the inner layer function, called the closure (Closure).
The feature of closures is that the returned function also refers to the local variables of the outer function, so to properly use closures, it is necessary to ensure that the referenced local variables do not change after the function returns. Examples are as follows:

You want to return 3 functions at a time, calculate 1x1,2x2,3x3 separately:

def count ():
FS = []
For I in range (1, 4):
def f ():
Return I*i
Fs.append (f)
Return FS
F1, F2, F3 = count ()
You might think that calling F1 (), F2 (), and F3 () results should be 1,4,9, but the actual results are all 9 (please do your own verification).
The reason is that when the count () function returns 3 functions, the value of the variable I referenced by these 3 functions has become 3. Since F1, F2, F3 are not called, they do not calculate i*i at this time, when F1 is invoked:

F1 ()
9 # Because F1 now calculates i*i, but now I has a value of 3.
Therefore, the return function does not refer to any loop variables, or to subsequent variables that change.
Learning tasks:

The return closure cannot refer to a loop variable, please rewrite the count () function to correctly return a 1x1, 2x2, 3x3 function that can be computed.
Examine the following function f:
def f (j):
def g ():
Return j*j
Return g
It can correctly return a closed packet g,g the variable J referenced is not a loop variable and therefore will execute normally.
Within the loop of the Count function, if you use the F function, you can avoid referencing the loop variable i.
Reference code:
def count ():
FS = []
For I in range (1, 4):
def f (j):
def g ():
Return j*j
Return g
R=f (i)
Fs.append (R)
Return FS
F1, F2, F3 = count ()
Print F1 (), F2 (), F3 ()
Results:
1 4 9
7. Anonymous functions

Higher-order functions can receive functions for parameters, and sometimes we do not need to explicitly define functions, and it is more convenient to pass in anonymous functions directly.
In Python, there is a limited amount of support for anonymous functions. As an example of the map () function, when calculating f (x) =x2, in addition to defining an F (x) function, you can also pass in the anonymous function directly:

Map (Lambda x:x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1, 4, 9, 16, 25 ,----------------------------------------------- Represents a function parameter. The
anonymous function has a limitation, that is, there can be only one expression, no return, and the return value is the result of the expression.
Using anonymous functions, you can create a function object directly without having to define the function name, and many times you can simplify the code:
Sorted ([1, 3, 9, 5, 0], lambda x, y:-cmp (x, y))
[9, 5, 3, 1, 0]
You can also return an anonymous function when returning a function:
Myabs = lambda x:-X if x < 0 else x
Myabs ( -1)
1
myabs (1)
1
Learning task:

The

uses anonymous functions to simplify the following code:
def is_not_empty (s):
return S and Len (S.strip ()) > 0
Filter (is_not_empty, [' Test ', None, ", ' str '," ', ' END ')
When you define an anonymous function, there is no return keyword, and the value of the expression is the function return value.
Print filter (lambda s:s and Len (S.strip ()) > 0, [' Test ', None, ', ' str ', ' ', ' END '])
Adorner @decorator:
What is decoration Manager
Problem: Define a function to dynamically add functionality while the function is running, and not to alter the code of the function itself.
Instance:
To print a function call with the Add Log function for the following functions:
def F1 (x):
return x*2
def f2 ():
return x*x
def f3 ():
Retur N x**x
Workaround:
Method 1:
Def F1 (x):
print ' Call F1 () '
return x*2
def f2 ():
print ' call F2 () '
Return x*x
def f3 ():
print ' Call F3 () '
Return x*x*x
Method 2:
Higher order function: You can accept a function as an argument, you can return a function, you can receive a function, wrap it, and then return a New function.
def f1 (x):
return x*2
def new_fn (f):
def fn (x):
print ' call ' + F. name + ' () '
Re Turn f (x)
return fn

The

First of all about the next adorner decorator.
Adorner effect:
Adorner. PNG
can greatly simplify the code and avoid writing repetitive code for each function
function:
Print log: @log
Detection performance: @performance
Database transaction: @transaction
URL route: @post ('/registel ')
8. Write parameterless decorator

The decorator of the

Python is essentially a high-order function that takes a function as an argument and then returns a new function. The
uses decorator with the @ syntax provided by Python to avoid manually writing F = Decorate (f) code.
Examine the definition of a @log:
def log (f):
def fn (x):
print ' call ' + F. name + ' () ... '
return f (x)
return FN
for the factorial function, @log works well:
@log
def factorial (n):
return reduce (lambda x,y:x*y, R Ange (1, n+1))
Print factorial
results:
call factorial () ...
3628800
However, for a function that is not a parameter, the call will error:
@log
def add (x, y):
return x + y
Print Add (1, 2)
Results:
Traceb ACK (most recent call last):
File "test.py", line at
Print Add (+)
Typeerror:fn () takes exactly 1 Argu ment (2 given)
because the Add () function needs to pass in two arguments, the @log writes dead a return function that contains only one argument.
to make @log adaptive to any function defined by a parameter, you can make use of Python's *args and **kw to ensure that any number of arguments are always properly called:
Def log (f):
def fn (*args, **kw):
print ' Call ' + F. name + ' () ... '
Return F (*args, **kw)
return FN
Now, for any function, @log will work correctly.
Learning tasks:

Write a @performance that can print out the time of the function call.

The time the function call is calculated can record the current timestamp before and after the call, and then calculate the difference of two timestamps.

Import time
def performance (f):
DEF fn (*args,**kw):
T1=time.time ()
R=f (*ARGS,**KW)
T2=time.time ()
print ' call%s () in%fs '% (f.name, (T2-T1))
Return r
RETURN fn
@performance
def factorial (n):
return reduce (lambda x,y:x*y, range (1, n+1))
Print factorial (10)
Experimental results:
Call factorial () in 0.000669s
3628800
9. Writing with parameter decorator

To examine the @log adorner in the previous section:
Def log (f):
def fn (x):
print ' call ' + F. name + ' () ... '
return f (x)
return FN
found that for the decorated function, the log-printed statement is immutable (except for the name of the function).
If the function is very important, want to print out ' [info] call XXX (), some functions are not very important, want to print out ' [debug] calls xxx () ... ', at this time, the log function itself will need to pass the ' info ' or ' debug ' parameters, Like this:
@log (' Debug ')
Def my_func ():
Pass
translates the above definition into a call to a higher-order function:
My_func = log (' Debug ') (My_func)
The above statement looks more like a comparison, and then expands:
Log_decorator = log (' DEBUG ')
My_func = Log_decorator (my_func)
The statement above is equivalent to:
Log_ Decorator = log (' DEBUG ')
@log_decorator
def my_func ():
Pass
Therefore, the log function with parameters first returns a decorator function, Let the decorator function receive the My_func and return the new function:
def log (prefix):
def log_decorator (f):
Def wrapper (*args, **kw):
Print ' [%s]%s () ... '% (prefix, F. name )
return F (*args, **kw)
return wrapper
return Log_decorator

@log (' DEBUG ')
def test ():
Pass
Print test ()
Execution Result:
[DEBUG] Test () ...
None
For this 3-layer nested decorator definition, you can first take it apart:

Standard decorator:

Def log_decorator (f):
def wrapper (*args, **kw):
print ' [%s]%s () ... '% (prefix, F.name)
Return f (*args, **kw)
Return wrapper
Return Log_decorator

Return to Decorator:

def log (prefix):
Return Log_decorator (f)
When you open it, the call will fail because in the 3-layer nested decorator definition, the outermost wrapper reference prefix, so it is difficult to break a closure into a normal function call. Programming languages that do not support closures require more code to implement the same functionality.
Learning tasks:

The previous section of @performance can only print seconds, please add a parameter to @performace, allow incoming ' s ' or ' MS ':
@performance (' Ms ')
def factorial (n):
return reduce (lambda x,y:x*y, range (1, n+1))
To implement a @performance with parameters, you need to implement:
My_func = Performance (' MS ') (MY_FUNC)
Requires 3 layers of nested decorator to be implemented.
Import time
def performance (unit):
Def perf_decorator (f):
def wrapper (*ARGS,**KW):
T1 = Time.time ()
R = f (*args,**kw)
T2 = Time.time ()
t = (t2-t1) * If unit== ' ms ' Else (T2-T1)
print ' call%s () in%f%s '% (f.name, t,unit)
Return r
Return wrapper
Return Perf_decorator
@performance (' Ms ')
def factorial (n):
return reduce (lambda x,y:x*y, range (1, n+1))
Print factorial (10)
10. Perfecting Decorator

@decorator can dynamically realize the increase of function function, however, after @decorator "transformation" function, compared with the original function, there is no other place than the function of a little more?
In the absence of decorator, print the function name:
def f1 (x):
Pass
Print F1.name
Output: F1
In the case of decorator, the function name is printed again:
def log (f):
def wrapper (*args, **kw):
print ' Call ... '
Return f (*args, **kw)
Return wrapper
@log
def f2 (x):
Pass
Print F2.name
Output: Wrapper
As you can see, the new function functions returned by decorator are not ' F2 ', but are @log internally defined ' wrapper '. This will invalidate the code that relies on the name of the function. Decorator also changed the function'sDocand other properties. If you want the caller to see that a function has undergone a @decorator transformation, you need to copy some of the properties of the original function into the new function:
def log (f):
def wrapper (*args, **kw):
print ' Call ... '
Return f (*args, **kw)
Wrapper.name= f.name
Wrapper.Doc= f.Doc
Return wrapper
It is inconvenient to write decorator because it is difficult to copy all the necessary properties of the original function to the new function, so Python's built-in Functools can be used to automate this "copy" task:
Import Functools
def log (f):
@functools. Wraps (f)
def wrapper (*args, **kw):
print ' Call ... '
Return f (*args, **kw)
Return wrapper
Finally, it is necessary to point out that since we have changed the original function signature (*args, **kw), we cannot get the original parameter information of the original function. Even if we use fixed parameters to decorate a function with only one parameter:
def log (f):
@functools. Wraps (f)
def wrapper (x):
print ' Call ... '
return f (x)
Return wrapper
It is also possible to change the parameter name of the original function because the parameter name of the new function is always ' x ', and the parameter name defined by the original function is not necessarily called ' X '.
Learning tasks:

Consider the @decorator with parameters, @functools. Where the wraps should be placed:
def performance (unit):
Def perf_decorator (f):
def wrapper (*args, **kw):
???
Return wrapper note that @functools.wraps should function on the new function returned.
Return Perf_decorator
Note that the @functools.wraps should function on the new function returned.
Import time, Functools
def performance (unit):
Def perf_decorator (f):
@functools. Wraps (f)
def wrapper (*ARGS,**KW):
T1=time.time ()
R =f (*args,**kw)
T2=time.time ()
t= (T2-T1) *1000 if unit== ' Ms ' Else (T2-T1)
print ' call%s () in%f%s '% (f.name, t,unit)
Return r
Return wrapper
Return Perf_decorator
@performance (' Ms ')
def factorial (n):
return reduce (lambda x,y:x*y, range (1, n+1))
Print factorial. name
11. Partial function

When a function has many parameters, the caller needs to provide multiple arguments. If you reduce the number of parameters, you can simplify the burden on the caller.
For example, the Int () function converts a string to an integer, and when only the string is passed in, the Int () function defaults to decimal conversion:

The

Int (' 12345 ')
12345
But the Int () function also provides an additional base parameter with a default value of 10. If you pass in the base parameter, you can do an N-ary conversion:
Int (' 12345 ', base=8)
5349
Int (' 12345 ', +)
74565
Suppose you want to convert a large number of binary strings, each time you pass in an int (x, base=2) is very troublesome, so, we think, can define a function of Int2 (), the default is to pass base=2 in:
def int2 (x, base=2):
return int (x, base)
So we convert the binary into Very convenient:
Int2 (' 1000000 ')
,
Int2 (' 1010101 ')
"
Functools.partial" is to help us create a biased function, we do not need to define INT2 (), You can create a new function directly using the following code:
Import functools
Int2 = functools.partial (int, base=2)
Int2 (' 1000000 ')
Int2
Int2 (' 1010101 ')

So, functools.partial can turn a function with a number of arguments into a new function with fewer parameters, and fewer parameters need to specify a default value at creation time, so the difficulty of the new function call is reduced.
Learning tasks:

? We can implement ignoring case ordering by passing in a custom sort function in the sorted this high-order function. Please use functools.partial to turn this complex call into a simple function:
Sorted_ignore_case (iterable)
To fix the CMP parameter for sorted (), you need to pass in a sort function as the default value for the CMP.
Import Functools
Sorted_ignore_case = functools.partial (Sorted,cmp=lambda s1,s2:
CMP (S1.upper (), S2.upper ()))
Print Sorted_ignore_case ([' Bob ', ' about ', ' Zoo ', ' credits ')

Life was short,i use Python.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

How I started to understand Python functional programming--python functional programming first involved

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.