Access to personal use only, please correct me if wrong also.
It is a functional programming abstract computing programming model.
Functional programming features
1, calculated as a function rather than the command.
2, functions written in a purely functional programming language is not variable.
3, supports higher-order functions, concise code.
Python supports functional programming supports the following features
1, not a purely functional programming: allows variable.
2, supports higher-order functions : functions can also be passed as a variable
3, support for closures : With the closure will be able to return function.
4, limited support for anonymous functions .
Higher-order functions
Direct definition: receiving function can function as arguments.
He began to explain
Variables can point to functions
It means the function itself can be assigned to a variable
a = abs print(abs) # output:<built-in function abs> print(a) # output:<built-in function abs>
Since the assignment is successful, is not it also can be called?
a = abs print(a(-10)) # output:10
objk
, Explanatory variablea
now points to theabs
function itself. Calla()
functions and callabs()
completely identical .The function name is variable
Generally it means that the function name is the variable to point to the function.
abs
This variable points to theabs
function.That is, if you
abs
point to other functions , itabs()
will not be the absolute value of the function.Examples
abs = len # 把abs这个变量指向len函数 print(abs) # 此时abs它就是一个len函数,<built-in function len> print(abs(10)) # 你想要去求绝对值,是会报错的。 print(abs([1,2,3])) # 而是需要你求长度。3前面两
It should be said plainly a.
Since variables can point to a function, a function that can receive another function as a parameter, which is the higher-order functions .
Experience the most simple higher-order functions
import math def sqrt_add(x, y, f): return f(x) + f(y) print(sqrt_add(25, 9, math.sqrt)) # output:8.0
Python built-in four higher-order functions
map()
This function, it receives a function and a iterable .
map
The function of the incoming sequence are sequentially applied to each element .And return the results as a new iterator. Yes, map it is an object returned iterator .
To obtain specific data, by
next()
the method. It can alsolist()
function.Examples
def f(x): return x * x print(list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]))) # output:[1, 4, 9, 16, 25, 36, 49, 64, 81] # 首字母大写,后续字母小写的规则 def format_name(s): return s[0].upper() + s[1:].lower() print(list(map(format_name, ['adam', 'LISA', 'barT']))) # output:['Adam', 'Lisa', 'Bart']
reduce()
This function receives parameters and
map()
the like.But the behavior and
map()
differentreduce()
incoming function f must receive two parameters,reduce()
forlist
each element called repeatedlyWith the function
f
, and returns the final result value.By summing quadrature to simplify its understanding. Of course, it can be directly summed with Python sum (), where in order to understand.
from functools import reduce def f(x, y): return x + y print(reduce(f, [1, 3, 5, 7, 9])) # output:25 # 还可以接收第三个参数,作为计算的初始值。 print(reduce(faa, [1, 3, 5, 7, 9], 100)) # output:125 # 第二个例子,求积函数 def prod(x, y): return x * y print(reduce(prod, [2, 4, 5, 7, 12])) # 3360
filter()
This function receives parameters and
map()
the like. The role of this function f is determined for each element, returnsTrue
orFalse
, ifIs
True
it to retain that element.Yes, with the results returned
map()
, it is part of iterators.Examples
# 从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数 def is_odd(x): return x % 2 == 1 print(list(filter(is_odd, [1, 4, 6, 7, 9, 12, 17]))) # output:[1, 7, 9, 17] # 删除None或者空字符串 def is_not_empty(s): return s and len(s.strip()) > 0 print(list(filter(is_not_empty, ['test', None, '', 'str', ' ', 'END']))) # output:['test', 'str', 'END']
Seen,
filter()
function returns a sequence from a qualified sieve element.sorted()
The core ranking algorithm is to compare the size of two numbers. If it is a string or a dictionary it? With the size of mathematics does not make sense, to be
To compare by abstract functions.
Sort of list
print(sorted([23, -454, 11, -6, 5])) # output:[-454, -6, 5, 11, 23]
Acceptable
key
function to implement custom sorting.print(sorted([23, -454, 11, -6, 5], key=abs)) # output:[5, -6, 11, 23, -454] # key指定的函数将作用于list的每一个元素上,并把返回的结果进行排序。
Sorting strings, in accordance with the size of the ASCII comparison.
Now propose to ignore case, then sorted, we do not need the whole first string changed to lowercase.
According to the previous example, simply by
key
processing to the received function.print(sorted(["harden", "Durant", "jordan", "curry", "O'Neal"], key=str.lower)) # output:['curry', 'Durant', 'harden', 'jordan', "O'Neal"]
To sum up:
sorted()
the essence of the sort function is to implement a mapping function.
Return function
Function as a return value
Directly example to analyze
def f(x): print("run f_function ...") def g(): print("run g_function ...") return x return g print(f(5)) # output: run f_function ... <function f.<locals>.g at 0x0000017364A0BF28> # 当调用f函数时,返回的并不是x的值,而是g函数。 # 要去调用g函数,才会返回x的值 print(f(5)()) # output: run f_function ... run g_function ... 5 is ok
In this example, the function
f
in turn defines a functiong
, and the function of internalg
reference an external functionf
parameters and local variables.When the
f
function returnsg
, the parameters and variables are stored in the function returned. This is called "closure" .Closure
Characteristics of the closure is returned by the function further reference to the outer function of local variables and parameters .
Look simple, but it is still to use the difficult of.
Now let you implement a function with closure, were calculated
1x1
,2x2
,3x3
def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f3 = count() print(f1(), f2(), f3())
Your desired outcome is 1,4,9. I hope so. The actual output is 9,9,9
The reason is that when
count()
the function returns the three functions, the value of the variable three functions referenced i has become 3. When you go to call it isf1()
-> return value is 9.Therefore, the function returns do not refer to any loop variables or variable subsequent changes occur .
To correct the above function
def count(): fs = [] for i in range(1, 4): def f(i): return lambda : i*i fs.append(f(i)) return fs f1, f2, f3 = count() print(f1(), f2(), f3())
The original
return i*i
replacedreturn lambda : i*i
. Uselambda
an anonymous function.The reason is the same parameter binding function together with the value unchanged.
Anonymous function
With
map()
function as an example, again calculatedf(x)
= x², before the method is to define a function.def f(x): return x * x print(list(map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
Now the way is a direct write anonymous function
print(list(map(lambda x: x*x, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
Obviously,
lambda x: x * x
that functionf()
.Keyword lambda represents the anonymous function, before the colon
x
represents a function parameter .Anonymous function has a limit, that is only one expression, do not write return, the return value is the result of the expression.
Of course, anonymity is a function object, can be assigned to a variable, and then use a variable to call the function.
Decorator
Without modifying the original function of the premise, the dynamic new features to it . Called "decorator."
It returns a new function by higher-order functions
def f1(x): return x * 2 def new_fn(f): def fn(x): print("call " + f.__name__ + " ()") return f(x) return fn g1 = new_fn(f1) print(g1(5)) # 这种调用方式的结果:f1的原始定义函数被彻底隐藏了。 f1 = new_fn(f1) print(f1(5))
Python built-in @ syntax is to simplify decorator calls
@new_fn
==f1 = new_fn(f1)
No reference decorator
From the previous description, we know the nature of Python decorator is a higher-order function that accepts a function as a parameter, then
After the return to a new function.
Introducing the ultimate combined function mentioned spiral.
from functools import reduce def log(f): def fn(x): print 'call ' + f.__name__ + '()...' return f(x) return fn # 首先是factorial函数要去调用是可型的。因为只要一个参数。 @log def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print(factorial(10)) # 那如果add函数也要去调用这个装饰器就会报错,因为有两个参数,不匹配。 @log def add(x, y): return x + y print(add(1, 2))
Let the
@log
adaptive function any parameters defined, can be used*args
and**kw
, to ensure that any number of arguments always normal call.Amendment
def log(f): def fn(*args, **kw): print('call ' + f.__name__ + '()...') return f(*args, **kw) return fn
Parameterized decorator
Examples
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())
This layer 3 is nested. You only need to understand the parameterized decorator usually takes three layer loop, you can go to write according to this template.
Here's a simple talk about:
@log('DEBUG') def test(): pass # 这个定义相当于是 test = log('DEBUG')(test) # 再进行转换 log_decorator = log("DEBUG") test = log_decorator(test) # 再进行转换就是 log_decorator = log("DEBUG") @log_decorator def test(): pass # 所以,带参数的log函数首先返回一个decorator函数,再让这个decorator函数接收test并返回新函数。
Whether or not understood, reference is now going resolved with the decorative instance code execution flow.
First execution
log("DEBUG")
, returns thelog_decorator
function, then the function call returns, the parameters aretest
a function, returnThe final value is
wrapper
a function.Perfect decorator
In fact, the above two methods basically get away, why perfect, because the original function plus a decorator, so the original letter
The number of the function name becomes the function name of the new function. More than a as an example,
test
the function name becomeswrapper
.You can
__name__.py
get to the function name. This means that the code-dependent function names will fail, such astest.__doc__
And other attributes. The original function is required__name__
to copy attributes to otherwrapper()
functions.Python For convenience, the need to write
wrapper.__name__ = f.__name
,wrapper.__doc__ = f.__doc__
Such an operation. Like directly into the module.By
functools
this tool to complete the replication process.import functools def log(f): @functools.wraps(f) def fn(*args, **kw): print('call ' + f.__name__ + '()...') return f(*args, **kw) return fn def log(prefix): def log_decorator(f): @functools.wraps(f) def wrapper(*args, **kw): print('[%s] %s()...' % (prefix, f.__name__)) return f(*args, **kw) return wrapper return log_decorator
These are modified decorator part. As can be seen further directed to a method of writing on the front function.
Partial function
Mentioned a
functools
module that many functions, one of which is a partial function.The biasing function is to reduce the function call difficult.
I mentioned in the chapter function, by setting the parameter default values to reduce the difficulty of function calls.
Inside the function mentioned
int()
functions, may be binary conversion. But the default is decimal.In order to avoid each call is
int(x, base=2)
, we write a function. To customize.functools.partial
Can be a function of many parameters become less of a new parameter function, fewer parameters need to specify the default when you createValue, so that the difficulty of the new function calls is reduced.
import functools int2 = functools.partial(int, base=2) print(int2('1000000')) # output:64 print(int2('1010101')) # output:85
Finally, add this: When you create a partial function, can actually receiving function objects,
*args
and**kw
these three parameters.