# -*- coding:gb2312 -*- #coding=utf-8 # 高阶函数 import math def is_sqr(x): y = int(math.sqrt(x)) return x == y*y print filter(is_sqr, range(1, 101)) # 返回函数 # 作用:延迟执行 def calc_prod(lst): def lazy_prod(): def f(x,y): return x*y return reduce(f, lst) return lazy_prod f = calc_prod([1, 2, 3, 4]) print f() # 匿名函数 print filter(lambda s: s and len(s.strip()) > 0, ['test', None, '', 'str', ' ', 'END']) # 装饰器 @decorator print "....装饰器...." def log(f): # 写法一 # def fn(x): # print 'call ' + f.__name__ + '()...' # return f(x) # return fn # 写法二 print 'call ' + f.__name__ + '()...' return f @log def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10) # 无参数装饰器 print "....无参数装饰器...." import time # 写法一,接收一个函数返回一个新函数,但是返回的新函数必须符合原函数的调用规则,即参数应该一致。 # 如,log()是无参函数,则调用就不能传递参数 def performance(f): def log(x): print time.time() return f(x) return log # 写法二,不用函数封装,直接添加新的操作 def performance2(f): print time.time() return f # 写法一优化,被装饰的函数前后可以执行不同的操作,即,返回的新函数可以在任意时候调用被装饰的函数 def performance3(f): def log(x): start_time = time.time() r = f(x) # 在新函数的此处调用被装饰函数,但是,此时被装饰函数尚未被调用,因为log函数尚未被调用,只是返回了函数对象 time.sleep(1) end_time = time.time() print 'call %s() in %fs' % (f.__name__, (end_time - start_time)) return r return log # 写法二优化,不用函数封装,直接添加新的操作 def performance4(f): start_time = time.time() r = f # 在此处调用被装饰函数 time.sleep(1) end_time = time.time() print 'call %s() in %fs' % (f.__name__, (end_time - start_time)) return r @performance4 def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10) # 带参数装饰器 print "....带参数装饰器...." def performance_parm(unit='s'): def performance5(f): def log(x): start_time = time.time() r = f(x) # 在新函数的此处调用被装饰函数,但是,此时被装饰函数尚未被调用,因为log函数尚未被调用,只是返回了函数对象 time.sleep(1) end_time = time.time() print 'call %s() in %fs %s' % (f.__name__, (end_time - start_time), unit) return r return log return performance5 @performance_parm('M') def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print factorial(10) # 完善decorator print "....完善decorator...." print factorial.__name__ # => log # 可见,由于decorator返回的新函数函数名已经不是'f2',而是@log内部定义的'wrapper'。这对于那些依赖函数名的代码就会失效。 # decorator还改变了函数的__doc__等其它属性。 # 如果要让调用者看不出一个函数经过了@decorator的“改造”,就需要把原函数的一些属性复制到新函数中。 # Python内置的functools可以用来自动化完成这个“复制”的任务 import functools def performance5(f): @functools.wraps(f) def log(x): start_time = time.time() r = f(x) # 在新函数的此处调用被装饰函数,但是,此时被装饰函数尚未被调用,因为log函数尚未被调用,只是返回了函数对象 time.sleep(1) end_time = time.time() print 'call %s() in %fs %s' % (f.__name__, (end_time - start_time), unit) return r return log @performance5 def factorial(n): return reduce(lambda x,y: x*y, range(1, n+1)) print "....装饰器修改后...." print factorial.__name__