装饰器
装饰器---装饰器就是一个函数,是一个用来修饰别的函数的函数
装饰器是由3部分组成的, 高阶函数+函数嵌套+闭包 3部分组成,其实说白了就是 高阶函数+闭包组成 因为函数嵌套其实就是闭包
//高阶函数
参数是函数名或者返回值是函数名就叫高阶函数,之前有讲过,自己回去复习
//闭包
闭包就是函数嵌套,只不过现在把函数的作用域换个名字改成叫包,闭包就是在每层包里封装的变量,下面举个例子
def father(name)://最外层的包叫 father ,它里面封装的变量是 name 和 son ,函数即变量所以son也是father这层包封装的变量 print("我是%s" % name) def son()://第二层包叫 son ,它封装的变量是 name 和 grandson name = "DJH" print("我的爸爸叫%s" % name) def grandson()://最里面的包叫 grandson ,里面没有封装啥变量 print("我的爷爷叫%s" %name) grandson() son() return None father("djh") 结果 我是djh 我的爸爸叫DJH 我的爷爷叫DJH //这个就叫函数的嵌套,在函数里面再定义函数,同时也叫闭包
//装饰器真正上阵-----没有参数的装饰器
//被修饰的函数没有参数
import time def test(): time.sleep(2) print('test is passed!') def timeer(func): def wrapper(): start_time = time.time() func() stop_time = time.time() print("test函数执行时间为:%s" % str(stop_time-start_time)) return None return wrapper test = timeer(test)//这样不太完美,因为每次有需要写这个,可以用python提供的语法省去这一步 test() 结果 test is passed! test函数执行时间为:2.0014126300811768 import time def timeer(func): def wrapper(): start_time = time.time() res = func() stop_time = time.time() print("test函数执行时间为:%s" % str(stop_time-start_time)) return res return wrapper @timeer//这一步相当于test = timeer(test),这样就不需要修饰函数时都加这一步了,先在这个@timeer这样写更美观 注意修饰函数必须写在被修饰的函数前面,不然报错 def test(): time.sleep(2) print('test is passed!') return "这是test的返回值" res = test() print(res) 结果 test is passed! test函数执行时间为:2.0014126300811768 这是test的返回值//就被修饰函数的返回值这里重点看一下
//被修饰的函数带参数
其实带参数的装饰器是怎么样的呢,因为装饰器是给被修饰的函数添加一个新功能,也就是说添加的一个新功能就写成装饰器就ok,但是这个被修饰的函数是千般万化的,它的参数的个数也各不相同的,那现在你想到了什么?就是在装饰器里加上收集参数呀,下面举例说明:
import time def timeer(func): def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) stop_time = time.time() print("test函数执行时间为:%s" % str(stop_time-start_time)) return res return wrapper @timeer def test(name,age)://两个参数 time.sleep(2) print('test is passed!','namme:'+name,'age:'+str(age)) return "这是test的返回值" @timeer def test1(name,age,gender)://三个参数 time.sleep(2) print('test1 is passed!','namme:'+name,'age:'+str(age),'gender:'+gender) return "这是test1的返回值" test('djh',18)//这一步其实是调用wrapper()函数,在其内部有个func()函数,因为@timeer<==>test=timeer(test),所以func其实就是test,因为wrapper()函数的参数是 //收集参数,故args是一个二元组,将其解包再传给func()函数,相当于直接传两个参数给test()函数 test1('djh',18,'male')//这个也一样只不过现在func相当于test1,args相当于三元组,将其解包传给func相当于直接传3个参数给test1 结果 test is passed! namme:djh age:18 test函数执行时间为:2.000821590423584 test1 is passed! namme:djh age:18 gender:male test函数执行时间为:2.001034736633301
//小知识补充,解压序列
my_list=[2,5,1] a,b,c=my_list print(a) print(b) print(c) 结果 2 5 1 my_list=[1,6,3,76,4,3,2,5,7,8,6] a,b,*_,c=my_list//*是标识符,标识着后面的那个符号也就是 _ 相当于列表中间的全部元素----一个元组,a第一个,b第二个,c最后一个 print(a,b,c) print(_) 结果 1 6 6 [3, 76, 4, 3, 2, 5, 7, 8]
//来一个验证用户是否登陆的装饰器吧,就是京东那些店,点开一些东西是要验证你是否登陆的
user_dic=( {'name':'djh','password':'123'}, {'name':'DJH','password':'123'}, {'name':'hhh','password':'123'}, {'name':'xxx','password':'123'}, {'name':'bbb','password':'123'} ) current_dic={"name":None,'password':None} def code_check(func): def wrapper(*args,**kwargs): if current_dic['name'] and current_dic['password']: res = func(*args,**kwargs) return res username = str(input('请输入用户名:')).strip() password = str(input('请输入密码:')).strip() for each in user_dic: if username == each['name'] and password == each['password']: current_dic['name']=username current_dic['password']=password res = func(*args,**kwargs) return res print("用户名或密码错误!") return None return wrapper @code_check def index(): print("欢迎来到主页") return None @code_check def shopping_car(name): print("%s,欢迎来到购物车!" % name) return None @code_check def home(name): print("%s,欢迎来到购物车!" % name) return None index() print("before-->",current_dic) home("大帅哥djh") print("after-->",current_dic) shopping_car('handsome boy djh')
//装饰器真正上阵-----带参数的装饰器
def decorator(data_type="filedb"): def decorator_true(func): def wrapper(*args,**kwargs): print("使用的数据库是:%s" % data_type) if data_type == 'filedb': res = func(*args,**kwargs) return res elif data_type == 'labdb': print("会你妈卖批") return None else: print("自己玩蛋去") return None return wrapper return decorator_true @decorator()//这里我得着重讲一下,对于python的@语法,也就是装饰器的一个语法来说呀,@后面跟的某一个函数的函数名,也就是函数的内存地址,则该函数就是这个被修饰的函数的 //装饰器,而这里是decorator(),这是什么呢?是函数名后面加了个(),意味着这个是必须调用的函数,然后返回值再和@结合,@decorator()<---->@decorator_True这是什么呢? //因为decorator()函数的返回值是decorator_true的函数名,也就是返回了一个真真正正的装饰器的内存地址decorator_True的内存地址 def test(name,age): print('name is %s,age %s' %(name,age)) return None @decorator('labdb') def test1(name,age,gender): print('name is %s.age %s,gender %s' %(name,age,gender)) return None test('djh',18) test1('DJH',18,'male') 结果 使用的数据库是:filedb name is djh,age 18 使用的数据库是:labdb 会你妈卖批