装饰器--装饰器类

装饰器的作用:

简单来说,可以把装饰器理解为一个包装函数的函数,它一般将传入的函数或者是类做一定的处理,返回修改之后的对象。
所以我们能够在不修改原函数的基础上,在执行原函数前后执行别的代码,比较常用的场景有日志插入,事物处理等

我们知道,在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'
展开阅读全文

没有更多推荐了,返回首页