Python知识6 函数式编程和装饰器【多测师】
一、函数式编程之高阶函数 print(abs(-10)) 结果:10 <built-in function abs> —abs(-10)是函数调用 abs是函数本身 获得函数调用的结果 可以把结果赋值给变量 x=abs(-13) print(x) 结果:13 把函数本身赋值给变量 x=abs print(x) <built-in function abs>—-结论:函数本身可以赋值给变量 变量可以指向函数 通过该变量来调用这个函数 x=abs print(x(-12)) 结论:变量x已经指向了abs函数本身 直接调用abs()函数和调用变量x()完全相同 二、函数名 —函数名也是变量 1.函数名就是指向函数的变量 把abs看成变量 它指向一个可以计算绝对值的函数 2.abs函数定义在import builtins模块当中 三、函数可以指向变量 (高阶函数) 1.举例一个简单的高阶函数 def add(x,y,a): return a(x)+a(y) print(add(1,-2,abs)) 结果:3 四、高阶函数之map/reduce 1.Python內建的函数 2.代码实现: def f(x): return x*x r=map(f,[1,2,3,4,5]) print(list(r)) 3.不用map()函数 直接写一个循环来进行计算 def f(x): return x*x L=[] for n in [1,2,3,4,5]: L.append(f(n)) print(L) 4.reduce 求一个序列的和 from functools import reduce def add(x,y): return x+y print(reduce(add,[1,3,5,7,9])) 运行结果:25 5.reduce內建函数 from functools import reduce def fn(x,y): return x*10+y print(reduce(fn,[1,3,5,7,9])) 五、高阶函数之filter 1.python內建filter()函数用于过滤序列 根据返回值的true和false 决定是否保留或丢弃该元素 def is_odd(n): return n%2 == 1 print(list(filter(is_odd,[1,3,5,8,19]))) 结果:[1, 3, 5, 19] 2.把序列的空字符串删除 def no_empty(s): return s and s.strip() print(list(filter(no_empty,['A','','B',None,'C','']))) 3.用filter求素数 def _odd_iter(): n = 1 while True: n = n+2 yield n def _not_divisible(n): return lambda x:x%n>0 def primas(): yield 2 it =_odd_iter() while True: n = next(it) yield n it = filter(_not_divisible(n),it) for n in primas(): if n <1000: print(n) else: break 六、高阶函数之sorted 1.排序算法 sorted排序 print(sorted([36,12,3,6,91])) 2.按绝对值排序 接受一个key函数实现自定义排序 print(sorted([-12,4,7,19,-1],key=abs)) 3.字典串排序 传入key值可以忽略字母的大小写进行排序 print(sorted(['bob','about','zoo','credit'],key=str.lower)) 4.倒叙排序 加上reverse=True print(sorted(['bob','about','zoo','credit'],key=str.lower,reverse=True)) 七、返回函数 1.返回函数:函数作为返回值 def lazy_num(*args): #在lazy_num中定义了函数sum 内部函数sum可以引用外部函数 def sum(): #lazy_num的参数和局部变量 ax = 0 for n in args: ax=ax+n return ax return sum p1=lazy_num(1,2,7,12,13) p2=lazy_num(87,34,1,41) print(p1()) print(p2()) 2.什么叫闭包? 就是在一个函数里面定义了一个新的函数,这个新的内部函数可以引用外部函数的参数和局部变量,当外部函数返回内部函数的时候,相关的参数和变量都保存在返回的参数中这种就称为闭包。。。 3.接上面 返回的函数在其定义内部引用了局部变量args 当一个函数返回一个函数后 其内部的局部变量被新函数引用,而且要用p1()调用 直接用p1是调用不了的 八、匿名函数 1.以map()函数为例,计算f(x)=x2时,除了定义一个f(x)的函数外,还可以直接传入匿名函数: list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])) 2.匿名函数lambda x: x * x实际上就是: def f(x): return x * x 3. 关键字lambda表示匿名函数,冒号前面的x表示函数参数。匿名函数只能有一个表达式 不用写return 返回值就是该表达式的结果 4.匿名函数式一个函数对象,可以把匿名函数赋值给一个变量 再利用变量来调用该函数 >>> f = lambda x: x * x >>> f <function <lambda> at 0x101c6ef28> >>> f(5) 25 5.也可以把匿名函数作为返回值返回 def build(x, y): return lambda: x * x + y * y 九、装饰器 1.装饰器:函数也是一个对象 且函数对象可以被赋值给变量 所以变量也能调用该函数 >>> def now(): ... print('2015-3-25') ... >>> f = now >>> f() 2015-3-25 2.函数对象有一个__name__属性,可以拿到函数的名字 >>> now.__name__ 'now' >>> f.__name__ 'now' 3.装饰器(Decorator):假设要增强now()函数的功能,又不希望修改now()函数的定义 这种在代码运行期间动态增加功能的方式称为:装饰器(Decorator) 代码如下: def log(func): def wrapper(*args,**kw): print('call %s:' % func.__name__) return func(*args,**kw) return wrapper @log def now(): print('2018-05-08') now() 十、偏函数 1.通过设定参数的默认值,降低函数调用的难度 int()函数可以把字符串转换为整数 >>> int('12345') ---int()函数默认按十进制转换 12345 print(int('12345',base=8)) ---传入base参数 可以做2-36进制转换 2.转换大量的二进制字符串 def int2(x,base=2): return int(x,base) print(int2('1000000')) 3.创建偏函数 实际上固定了int()函数的关键字参数base import functools int2=functools.partial(int,base=2) print(int2('10101')) 4.args=(10,5,6,7,) print(max(*args))