Functional Programming
高阶函数返回函数匿名函数装饰器偏函数高阶函数
面向过程的程序设计:把大段代码拆成函数,通过一层层函数调用,可将复杂任务分解成若干简单的任务函数是面向过程的程序设计的基本单位计算机Computer&&计算compute:
Computer:CPU执行指令代码进行加减乘除运算,及各种条件判断和跳转指
Compute:数学意义的计算
汇编语言是最贴近计算机的语言
越低级的语言,越贴近计算机,抽象程度低,执行速度快 c
越是高级的语言,越远离计算机,抽象程度高,执行效率低 lisp函数式编程的特点:函数可以作为参数,或作为返回值Python不是纯函数式编程语言
返回函数
使用场景:后续代码中仍可能需要使用的函数返回函数即使调用相同的参数,返回的也是不同的新函数def lazy_sum(*args):def sum():ax = 0for n in args:ax = ax + nreturn axreturn sum
调用lazy_sum(*args)时,每次返回新的函数
>>> f1 = lazy_sum(1,3,5,7,9)# f1返回的是函数sum>>> f1<function lazy_sum.<locals>.sum at 0x102f32158>>>> f1()25>>> f2 = lazy_sum(1,3,5,7,9)# f2返回的是一个新的函数sum>>> f1 == f2# f1与f2传入相同的参数,但在调用的时候,每次返回新的函数False
闭包:调用一个函数返回一个函数后,其局部变量被新函数引用
>>> def count():...fs = []...for i in range(1, 4):... def func():... return i*i... fs.append(func)...return fs>>> f = count()# 返回三个函数组成的列表>>> f# 三个函数不相同[<function count.<locals>.f at 0x1091540d0>, <function count.<locals>.f at 0x109154400>, <function count.<locals>.f at 0x109154488>]>>> f[1]()# 先返回三个函数,后执行函数。故此时,他们引用的变量均为39>>> f[2]()9>>> f[3]()9
tips:返回闭包时,返回函数尽量不要引用循环变量,或后续会发生变化的变量
匿名函数
lambda()
使用场景:传入不需要显示定义的函数使用限制:只能有一个表达式,不能return,返回表达式的结果
>>> list(filter(lambda x : x % 2 == 1, range(1, 20)))[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
装饰器
使用场景:调用函数前自动打印日志,但不修改函数定义自定义装饰器Decorator步骤: 定义装饰器decoratordef log(text = ''):def decorator(func):def wrapper(*args, **kw):# func.__name__用于获取函数名print('%s %s():' % (text, func.__name__))return func(*args, **kw)return wrapperreturn decorator
使用装饰器
@log('execute')def now():print('-05-06')
相当于:
>>> log('execute')(now)()execute wrapper():execute now():-05-06
缺点:原始函数的__name__ 变成为自定义的wapper解决方案: 使用Python内置的functions.wraps
import functoolsdef log(text = ''):def decorator(func):@functions.wraps()def wrapper(*args, **kw):print('%s %s():' % (text, func.__name__))return func(*args, **kw)return wrapperreturn decorator
偏函数
偏函数Partial function:通过设定参数默认值,降低函数调用的难度>>> import functools>>> int2 = functools.partial(int, base=2) # 将int()函数中base参数设置默认值为2
functools.partial设置默认参数后,可在函数调用时传入其他值;functools.partial最后接受函数对象、*args和**kw三部分参数
import functoolsdef add(*args, **kwargs):print(*args)print('-' * 20)for key, value in kwargs.items():print('%s : %s' % (key, value))add_partial = functools.partial(add, 10, k1 = 10, k2 = 20)print add_partial(10, 2, 3, k1 = 40, k3 = 30)
返回结果为
101023--------------------k1 : 40k2 : 20k3 : 30