写代码要遵循开发封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
封闭:已实现的功能代码块开放:对扩展开发故装饰器的出现就是解决以上问题的
一、什么是装饰器
装饰器本质就是函数,功能是为其他函数附加功能
二、装饰器遵循的原则
1、不修改被修饰函数的源代码
2、不修改被修饰函数的调用方式
三、实现装饰器的知识储备
装饰器=高阶函数+函数嵌套+闭包
装饰器的简单示例1:(在不修改源代码的基础上添加新的功能)
import time def timmer(func): def wrapper(): print(func) func() return wrapper @timmer#就相当于是装饰器的功能,将被装饰的index加入了新功能,即index=timmer(index)# def index(): time.sleep(2) print("welcome to beijing") index()执行结果是:
<function index at 0x000000000251B8C8> welcome to beijing装饰器示例2:(在不修改源代码的基础上添加计算运行时间的新的功能)
# #计算运行时间 import time#导入模块 def timmer(func):#这时候相当于def timmer(func)是def timmer(index) def wrapper(): print(func) #打印index的内存地址 start_time=time.time()#开始时间 func() #func()相当于index()#相当于执行index()原始函数 stop_time=time.time()#结束时间 print("run time is %s"%(stop_time-start_time))#第八步 return wrapper# @timmer#是装饰器的功能,将被装饰的index加入了新功能,即index=timmer(index) def index(): time.sleep(2) print("welcome to beijing") index()#由于上面def index()是def timmer(index)(),timmer(index)的执行结果是wrapper, # 故而执行index函数就相当于是执行wrapper()
执行结果是:
<function index at 0x00000000024CB8C8> welcome to beijing run time is 2.0001144409179688如图示例:
什么叫高阶函数呢??
高阶函数定义:1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数
高阶函数示例1:(函数接受的参数是一个函数名)
def foo(): print('from foo') def foo_1(func): print('from foo_1') func() def foo_2(func): print('from foo_2') return func foo_1(foo)#将函数名foo当做参数 foo_2(foo)#将函数名foo当做参数执行结果是:
from foo_1 from foo from foo_2高阶函数示例2:(函数的返回值是一个函数名)
def foo(): print('from foo') def foo_1(func): print('from foo_1') func() return func foo=foo_1(foo) print(foo)执行结果是:
from foo_1 from foo <function foo at 0x0000000001D13E18>高阶函数总结1.函数接收的参数是一个函数名 作用:在不修改函数源代码的前提下,为函数添加新功能, 不足:会改变函数的调用方式2.函数的返回值是一个函数名 作用:不修改函数的调用方式 不足:不能添加新功能
装饰器:
无参装饰器:
示例1:
import time def timmer(func): def wrapper(*args,**kwargs): print(func)#打印的是home的内存地址 start=time.time() func(*args,**kwargs)#由于func为home,故而返回下面执行home函数,即home(“xuyuanyuan”) stop=time.time() print('run time is %s ' %(stop-start)) return wrapper @timmer#相当于home=timmer(home) def home(name): time.sleep(2) print('welcome to %s home page' %name) home('xuyuanyuan')#执行的是wrapper(“xuyuanyuan”),将xuyuanyuan当做参数传给wrapper(*args,**kwargs)这个函数执行结果是:
<function home at 0x000000000254B8C8> welcome to xuyuanyuan home page run time is 2.0011146068573示例2:
##无参装饰器(有参函数) import time def timmer(func): def wrapper(*args,**kwargs):#wrapper('egon','123') start_time=time.time() func(*args,**kwargs) #相当于执行该auth('egon','123')函数,将egon 123当做参数传给函数auth(name,password),故而输出print('egon','123') stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return wrapper @timmer #auth=timmer(auth) def auth(name,password): print(name,password) auth('egon','123') #wrapper('egon','123')执行结果是:
egon 123 run time is 0.0示例3:
##判断最大值,并输出它的运行时间 import time def timmer(func):#相当于def timmer(my_max) def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) #my_max(1,2) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timmer#my_max=timmer(my_max) def my_max(x,y): print('my_max function') res=x if x > y else y return res res=my_max(1,2) #res=wrapper(1,2) print('=====>',res)执行结果是:
my_max function run time is 0.0 =====> 2
有参装饰器(即2层闭包函数)
示例:
def auth2(auth_type): def auth(func): # print(auth_type) def wrapper(*args,**kwargs): if auth_type == 'file': with open("file.txt", mode="r", encoding="utf8") as f: file_list = f.readlines() name=input('用户名: ') passwd=input('密码:') if name in file_list: # 如果用户名在黑名单内 print("您的账户已锁定,请联系管理员!") if name == 'xyy' and passwd == '123': print('auth successfull') res=func(*args,**kwargs)#执行函数index() return res else: print('auth error') elif auth_type == 'sql': print('暂不支持') return wrapper return auth @auth2(auth_type='file') #auth2(auth_type='sql')的返回结果是author,故而@auth 相当于#index=auth(index) def index(): print('welcome to inex page') index()#运行函数index执行结果是:
用户名: xyy 密码:123 auth successfull welcome to inex page
多个装饰器的使用:
当需要使用多个装饰器的功能时,一般是先调用下面的@,再执行上面的@
举例说明:(给上述例子加入计算运行时间的功能)
import time#导入时间模块 current_login={'name':None,'login':False} ##定义运行时间函数 def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper ##定义用户登录调用账号密码的方式(文件还是数据库) def auth2(auth_type='file'): def auth(func): # print(auth_type) def wrapper(*args,**kwargs): if current_login['name'] and current_login['login']: res=func(*args,**kwargs) return res if auth_type == 'file': name=input('username: ') password=input('password: ') if name == 'xyy' and password == '123': print('auth successfull') res=func(*args,**kwargs) current_login['name']=name current_login['login']=True return res else: print('auth error') elif auth_type == 'sql': print('暂不支持') return wrapper return auth ##调用了2个装饰器,先执行@auth2(auth_type='file')再运行@timmer,由上至下 @timmer##再执行这个 @auth2(auth_type='file') #@auth #index=auth(index)##先执行这个 def index(): print('welcome to inex page') index()执行结果是:
username: xyy password: 123 auth successfull welcome to inex page run time is 12.809732437133789 welcome to inex page run time is 0.0转载于:https://www.cnblogs.com/xuyuanyuan123/p/6690218.html
相关资源:JAVA上百实例源码以及开源项目