一、定义
装饰器:本质是函数,为其他函数添加附加功能
原则:
1、不修改被修饰函数的源代码
2、不修改被修饰函数的调用方式
装饰器=高阶函数+函数嵌套+闭包
二、高阶函数
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述其中一个条件就是高阶函数
下例中是一个高阶函数:
def foo(): print("你好") def test(func):#是一个高阶函数 print(func)#func有了foo的内存地址 func()#运行foo函数 test(foo)
def foo(): print("来自foo") def test(func):#接收参数是函数名 func() return func#返回值还是函数名 foo=test(foo) foo()#还是执行原来函数的调用方式
三、装饰器实现
1、基本实现
import time def timmer(func): #func=test def wrapper(): start_time = time.time() func() #就是在运行test() stop_time = time.time() print('运行时间是%s' % (stop_time-start_time)) return wrapper @timmer #test=timmer(test) def test(): time.sleep(3) print('test函数运行完毕') test() #执行的是wrapper()
2、原本的函数有返回值
import time def timmer(func): #func=test def wrapper(): start_time = time.time() res = func() # 就是在运行test() stop_time = time.time() print('运行时间是%s' % (stop_time-start_time)) return res return wrapper @timmer #test=timmer(test) def test(): time.sleep(3) print('test函数运行完毕') return "这是test的返回值" res = test() print(res)
3、加上参数
import time def timmer(func): #func=test1 def wrapper(*args, **kwargs): #固定用法,不管原函数有几个参数,这种形式都能接收 start_time = time.time() res = func(*args, **kwargs) #就是在运行test1() func(*('alex'),**{'age':18;'gender':male;....}) stop_time = time.time() print('运行时间是%s' % (stop_time-start_time)) return res return wrapper @timmer def test1(name, age, gender, habit): time.sleep(1) print('test1函数运行完毕,名字是【%s】 年龄是【%s】 ,性别是【%s】,爱好是【%s】' %(name, age, gender, habit)) return '这是test的返回值' test1('alex',18,'male',"玩")
4、验证功能
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_dic={'username':None,'login':False} #全局变量,登录状态 def auth_func(func): def wrapper(*args, **kwargs): if current_dic['username'] and current_dic['login']:#有人开始登录,没人登录的话就直接不往下运行了 return 0 username = input('用户名:').strip()#用户输入用户名,程序把有输入内容前面的空格去掉 passwd = input('密码:').strip() for user_dic in user_list: if username == user_dic['name'] and passwd == user_dic['passwd']: current_dic['username']=username#改变登录状态,改变全局变量 current_dic['login']=True#意思就是现在有人登录 res = func(*args, **kwargs) return res else:#for也可以加else,说明for循环中没有匹配的 print('用户名或者密码错误') return wrapper @auth_func def index(): print('欢迎来到京东主页') @auth_func def home(name): print('欢迎回家%s' %name) @auth_func def shopping_car(name): print('%s的购物车里有[%s,%s,%s]' %(name, '奶茶', '妹妹', '娃娃')) print('before-->', current_dic)#先打印出登录状态 index() print('after--->', current_dic)#输入登录内容后的登录状态 home('产品经理')
5、带参数验证功能装饰器
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_dic={'username':None,'login':False} def auth(auth_type='filedb'):#在原来的装饰器基础上往上一层嵌套一个函数,变成一个新的装饰器 def auth_func(func): def wrapper(*args,**kwargs): print('认证类型是',auth_type) if auth_type == 'filedb': if current_dic['username'] and current_dic['login']: return 0 username=input('用户名:').strip() passwd=input('密码:').strip() for user_dic in user_list: if username == user_dic['name'] and passwd == user_dic['passwd']: current_dic['username']=username current_dic['login']=True res = func(*args, **kwargs) return res else: print('用户名或者密码错误') elif auth_type == 'ldap': print('鬼才特么会玩') res = func(*args, **kwargs) return res else: print('鬼才知道你用的什么认证方式') res = func(*args, **kwargs) return res return wrapper return auth_func @auth(auth_type='filedb') def index(): print('欢迎来到京东主页') @auth(auth_type='ldap') def home(name): print('欢迎回家%s' %name) # @auth(auth_type='sssssss') def shopping_car(name): print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃')) index() home('产品经理') shopping_car('产品经理')