python 函数装饰器
python 函数装饰器:
装饰器的作用就是在函数调用方法不变的情况下,把一个函数封装到另一个函数里面,执行这个函数时自己去调用另一个函数.
装饰器本质也是函数,(装饰其他函数)就是为其他函数添加附加功能.
一、了解装饰器之前,先看看下面这个列子.
#!/usr/bin/env python #coding:utf-8 def deco(arg): # arg=func arg() # arg() = func() def func(): print("Hello func ") deco(func) ------------------------------------------------------------------- #执行顺序 1.执行def deco(arg): 将其加载进内存.内容不执行 2.执行def func():将其加载进内存.内容不执行 3.执行deco(func) 给deco传的参数为func,这个参数为func()函数的函数名 4.执行def deco(arg): ===> arg = func ===> arg() ==func() 5.执行arg()即func()函数 ==> func() 6.打印出func()执行结果,即print("Hello func ") 总结:把一个函数func()封装到另一个函数deco(arg)里面,执行这个函数deco(func)时自己去调用另一个函数.
二、看看带 return 的函数
#!/usr/bin/env python #coding:utf-8 # 替换函数(装饰) # 装饰函数的参数是被装饰的函数对象,返回原函数对象 # 装饰的实质语句: test = deco(test) def deco(func): #func = test ==> func()=test() print("before") func() print("after") return func #return test函数内存地址 def test(): print("My test func") test = deco(test) # 重新定义了一个变量名test,指向deco(func),这样可以不用改变调用函数的名称. test() # 调用函数. ---------------------------------------------------- before My test func after My test func
上面的调用方式可以写成如下,执行结果一样.
#!/usr/bin/env python #coding:utf-8 def deco(func): #func = test ==> func()=test() print("before") func() print("after") return func #return test函数内存地址 @deco # test=deco(test) 等价于 @deco,学名为装饰器的语法糖 def test(): print("My test func") test() # 调用函数. ----------------------------------------------------- before My test func after My test func
使用双层装饰函数来给函数附加额外功能:
#!/usr/bin/env python #coding:utf-8 import time def timer(func): # func=test ==> timer(test): def deco(): start_time = time.time() func() #运行 test()函数 stop_time = time.time() print("run time %s" %(stop_time-start_time)) return deco #deco代表返回函数名,非执行函数, @timer # test=timer(test) def test(): time.sleep(2) print("Hello test1") test() #调用函数,在调用函数名不变的情况下,先执行装饰函数中的deco()块,在执行test()函数. ------------------------------------------------------------ Hello test1 run time 2.0001144409179688 #总结: @timer <==> test=timer(test)这句,是简化的写法.使用语法糖@来装饰函数 @timer 等于函数执行了两次: 1.执行timer函数,把被装饰的函数作为参数timer(test) 2.将timer函数的返回值,赋值给被装饰的函数的函数名.
那么问题来了,被装饰的函数如果有参数呢,如下我要装饰test1和test2函数,test1没有参数,而test2有参数,这时候就用到了装饰器动态参数,
#!/usr/bin/env python #coding:utf-8 import time def timer(func): # func=test ==> timer(test): def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) #运行 test()函数 stop_time = time.time() print("run time %s" %(stop_time-start_time)) return deco #deco代表返回函数名,非执行函数, @timer # test=timer(test) def test1(): time.sleep(2) print("Hello test1") @timer def test2(name, age): print("Hello test2:", name, age) test1() #调用函数,在调用函数名不变的情况下,先执行装饰函数中的deco()块,在执行test()函数. test2("saneri",33) --------------------------------------------------------------- Hello test1 run time 2.0001144409179688 Hello test2: saneri 33 run time 0.0
下面我们来看一个简单的完整的用户登录认证的装饰器函数:
#!/usr/bin/env python #coding:utf-8 """ 知识点: 1.模拟网站登陆认证,home和bbs页面需要登陆才可以访问. 2.home 认证后有return返回值 """ user,passwd = "saneri","123" def auth(func): # func <==> home def wrapper(*args,**kwargs): username = input("Username:").strip() password = input("Password:").strip() if user == username and passwd == password: print("\033[31;1m请输入用户名和密码认证\033[0m") return func(*args,**kwargs) # <==> home(*args,**kwargs) else: exit("\033[31;1m认证失败,用户名或密码错误!\033[0m") return wrapper def index(): print("Welcom to index page !") @auth # home = auth(home) def home(): print("Welcom to home page !") images_list = ['views','images','template','video'] return images_list @auth #bbs = auth(bbs) def bbs(): print("Welcom to bbs page !") index() ret = home() print(ret) bbs()
参考链接:https://www.cnblogs.com/saneri/p/4992586.html

浙公网安备 33010602011771号