装饰器的作用:
简单来说,可以把装饰器理解为一个包装函数的函数,它一般将传入的函数或者是类做一定的处理,返回修改之后的对象。
所以我们能够在不修改原函数的基础上,在执行原函数前后执行别的代码,比较常用的场景有日志插入,事物处理等
我们知道,在python中函数也是被视为对象的,可以作为参数传递,那么假如把计算机耗时的独立为一个单独的函数,然后把需要计算耗时的函数都不用修改自己的代码了
普通装饰器:
from datetime import datetime
def log(func_name):
print('--日志--')
def wrapper(*args,**kwargs):
print('打印日志信息',datetime.now())
return func_name(*args,**kwargs) # 返回@log修饰函数之后的整体(包含@check)
return wrapper
def check(right_name):
print('--check1--')
def warpper1(func_name):
print('---warpper1-')
def warpper2(*args,**kwargs):
print('----验证当前用户是否具有%s权限--'%right_name)
# 假如有权限
return func_name(*args,**kwargs)
return warpper2
return warpper1
@log
@check('del_art')
def delart(id):
print('正在删除文章',id,datetime.now())
return {'status':'ok','msg':'删除成功!!!'}
# @check('update_art')
# def updateart(id):
# print('---正在修改文章---',id)
# return {'status':'ok','msg':'更新成功!!!'}
执行结果:
--check1--
---warpper1-
--日志--
In [14]:
# print(updateart(101))
delart(102)
执行结果:
----验证当前用户是否具有del_art权限--
打印日志信息 2018-07-16 11:30:12.139884
正在删除文章 102 2018-07-16 11:30:12.139954
{'status': 'ok', 'msg': '删除成功!!!'}
- 多层的装饰函数在初始声明时,会从内向外执行装饰函数,获取目标函数执行时的包装函数,在目标函数执行时,由上而下(装饰函数声明的顺序)来执行它的包装函数。如上面的@log装饰函数在目标函数执行时,返回log的wrapper包装执行的结果,实际是@check中wrapper2的包装函数。
- 如果装饰函数带有参数,则会在初始声明时,会调用这个函数来获取它的包装函数
装饰器类:
class CheckLogin:
def __init__(self,func_name):
self.func_name = func_name
print('--checklogin--',func_name)
def __call__(self,*args,**kwargs):
print('--check 用户是否登录--')
return self.func_name(*args,**kwargs)
class CheckRight:
def __init__(self,right_name):
self.right_name = right_name
def __call__(self,func):
def wrapper(*args,**kwargs):
print('--验证用户权限--',self.right_name)
return func(*args,**kwargs)
return wrapper
In [20]:
@CheckLogin # 无参数,则会将修饰的函数 bu yart传入到构造函数总,默认__call__是包装函数
@CheckRight('buy') # 有参数,会将参数传给传给构造函数__init__,且调用__call__是包装函数
def buyart(id):
print('正在购买文章',id)
return 'ok'
@CheckLogin
@CheckRight('reply')
def replyArt(id,msg):
print('评论文章',id,'内容:',msg)
return 'ok'
执行结果:
--checklogin-- <function CheckRight.__call__.<locals>.wrapper at 0x10c6d8158>
--checklogin-- <function CheckRight.__call__.<locals>.wrapper at 0x10c642488>
In [21]:
buyart(1000)
# replyArt(1000,'文章写的真不错')
执行结果:
--check 用户是否登录--
--验证用户权限-- buy
正在购买文章 1000
'ok'