第一个python高阶函数:
示例:计算一个值的阶乘(递归)
#!/usr/bin/env python#coding=utf-8def fact(n): if n <= 1: return n #递归函数必须有退出条件 return fact(n-1)*n #调用函数自身 最终格式为return 2*3*4*5*6*7*8*9*10f = fact(10) #python中函数递归最大深度为1000print f
执行结果:
[root@server24 ~]# ./func_9.py 3628800
在python中尽量避免递归,绝大多数都是可以转为迭代,因为迭代要比递归快的多。
同样利用迭代计算一个值的阶乘:
def fact(n): ret = 1 #设置初值 for i in range(n,1,-1): ret *= i return retprint fact(10)执行结果
[root@server24 ~]# ./func_9.py 3628800
在python中函数是一等对象,可以像值一样赋值,作为函数的返回值返回。
高阶函数
以函数对象作为参数的函数叫高阶函数:
下面为三个内置的高阶函数:
filter() 过滤: filter(function or none ,seq)当函数返回值为true时,会将序列的当前值加进来
>>> li = [1,2,3,4,5,6,7]>>> def f(x):... return x % 2 == 0... >>> filter(f,li)[2, 4, 6]
用高阶函数手动实现内置filter函数
#!/usr/bin/env python#coding=utf-8li = [1,2,3,4,5,6,7]def f(x): return x % 2 == 0 #return出去的是布尔值 true or falsedef afilter(f1,lis): lii = list() for i in lis: if f1(i): lii.append(i) return liist = afilter(f,li)print st
[root@server24 ~]# ./afilter.py [2, 4, 6]
map() 映射:对列表中每个元素执行一个函数
>>> li = [2,3,4,5,6,7]>>> def f(x):... return x * 2... >>> map(f,li)[4, 6, 8, 10, 12, 14]
用高阶函数手动实现高阶内置函数map()
#!/usr/bin/env python#coding=utf-8li = [1,2,3,4,5,6,7]def f(x): return x * 2def amap(f1,lii): lis = list() for i in lii: lis.append(f1(i)) return lisst = amap(f,li)print st
[root@server24 ~]# ./amap.py [2, 4, 6, 8, 10, 12, 14]
reduce() 化简:将每次迭代结果与下一个元素一同执行一个二元的func函数
>>> li = [2,3,4,5,6,7]>>> def sum(x,y):... return x * y... >>> reduce(sum,li)5040
用高阶函数手动实现内置reduce
#!/usr/bin/env pythonli = [0,1,2,3,4]def f(x,y): return x * ydef reduc(f1,lis): st = lis[0] for i in range(1,len(lis)): st = f1(st,lis[i]) return sts = reduc(f,li)print s
函数嵌套
嵌套一般格式:
def external(): def internal(): expression return internal #返回为嵌套,且与嵌套函数同级
示例:无参数函数嵌套
#!/usr/bin/env python#coding=utf-8def ext(): print 'this is external' def internal(): print 'this is internal' return internalf = ext() #调用函数ext,将返回函数internal赋值给变量ff() #实际调用的是嵌套函数
执行结果:
[root@server24 ~]# ./ext.py this is externalthis is internal
计算一个函数的执行时间
#!/usr/bin/env python#coding:utf-8import time import datetimedef func(arg): time.sleep(arg)def timezo(fun): def wrap(arg): start = datetime.datetime.now() fun(arg) end = datetime.datetime.now() cost = end - start# **.total.seconds()用于计算秒数,是python2.7较之前版本新加的功能 print "execute %s spend %s" % (fun.__name__,cost.total_seconds()) return wrapf = timezo(func) #返回函数wrapf(3) #再次调用函数wrap
Decorator 装饰器:其实也是一个函数,是用来包装函数的函数。
作用:解耦
在使用装饰器后返回一个修改之后的函数对象,将其重新赋值原来的标识符,并永久丧失对原始函数的访问。将**.__name__,**.doc__等等改为装饰器内return的函数的属性
如上计算函数执行时间的模块其实就是一个装饰器,一般用@来引用装饰函数
示例:
#!/usr/bin/env python#coding:utf-8import timeimport datetimedef deco(func): '''第一个decorator是装饰函数,它的参数用来加强装饰的,其内部必须建一个接受被装饰函数的函数,然后返回这个对象''' def new_deco(arg): '''装饰器里面一般原封不动地调用函数,不影响函数本身''' start = datetime.datetime.now() func(arg) end = datetime.datetime.now() cost = end - start print 'exeute %s spend %s' % (func.__name__,cost) return new_deco #必须返回@deco #在调用func函数之前引用装饰器def func(arg): '''一切皆对象''' time.sleep(arg)func(2)'''返回来的是修改后的函数对象,即为装饰器内return的函数的属性'''print func.__name__print func.__doc__执行结果:
[root@server24 ~]# ./deco.py exeute func spend 0:00:02.002529new_deco装饰器里面一般原封不动地调用函数,不影响函数本身
如果在使用装饰器时总是丢失函数本身的属性信息那将是很糟糕的事情,functools.wraps解决了这个问题,wraps在装饰器中可以将函数的函数名,文档字符串,参数信息等等复制过来
示例:#!/usr/bin/env python#coding:utf-8import timeimport datetimeimport functools #导入functools模块def deco(func): '''第一个decorator是装饰函数,它的参数用来加强装饰的,其内部必须建一个接受被装饰函数的函数,然后返回这个对象''' @functools.wraps(func) def new_deco(arg): '''装饰器里面一般原封不动地调用函数,不影响函数本身''' start = datetime.datetime.now() func(arg) end = datetime.datetime.now() cost = end - start print 'exeute %s spend %s' % (func.__name__,cost) return new_deco #必须返回@deco #在调用func函数之前引用装饰器def func(arg): '''一切皆对象''' time.sleep(arg)func(2)'''返回来的是修改后的函数对象,即为装饰器内return的函数的属性'''print func.__name__print func.__doc__执行结果:
[root@server24 ~]# ./deco.py exeute func spend 0:00:02.002885func一切皆对象