• 十四、装饰器


    装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。
    def f1(arg):
    arg()
     
    def func():
    print ('123')
     
    f1(func) ======>f1接收的参数是一个函数
     
     
    注:func返回的是内存地址,func()才是执行func这个函数
    =====================================================
    =====================================================
    =====================================================
    def f1():
    print 'f1' ========>连接数据库
    def f2():
    print 'f2' ========>连接redis
    def f3():
    print 'f3' ========>去硬盘拿数据
    。。。。。。。
     
    我这三个函数已经都写好了,并且已经都封闭了(即不能再往函数里面去做修改了),这个时候老板有个任务,希望对每个函数做验证,而函数又已经都是写好了的,已经封闭了,该怎么办?
    思路是这样的,还是上面的例子(语法是错误的,只是解释原理):
     
    def f1(arg):
    print (‘验证’)
    arg()
     
    def func():
    print ('123')
     
    #1.将被调用函数封装到另外一个函数里边
    func = f1(func)
    #2.将原函数重新赋值
    func()
     
    我们看见这样就解决了问题(只是原理,语法并不是这样)。
    =========================================================
    =========================================================
    =========================================================
    具体做法是这样的:
    def auth(func): =======>我在上边新加了一个具有验证功能的函数,下面执行这个函数,就会发现将f1作为参数传给func函数,以后 就等价于func = f1 ======>func() <======>f1()
    def inner(): ==========>函数里又嵌套一个函数
    print ('before')
    func() =========f1 =====>原函数
    return inner
     
     
     
     
    def f1():
    print 'f1' ========>连接数据库
    ret1 = auth(f1) = def inner():
    print ('before')
    f1()#原来f1
    f1 = ret1
     
    def f2():
    print 'f2' ========>连接redis
     
    ret2 = auth(f2) = def inner():
    print ('before')
    f2()#原来f2
     
    f2 = ret2
    def f3():
    print 'f3' ========>去硬盘拿数据
     
    ret3 = auth(f3) = def inner():
    print ('before')
    f3()#原来f3
     
    f3 = ret3
    。。。。。。。
     
     
    result = auth(f1) = def inner():
    print ('before')
    func()
     
    result() #它现在就等于执行inner()这个函数了,执行inner这个函数就是执行了f1这个原函数了
     
     
    上面的写法是为了理解装饰器的原理和工作过程,不过自己都看不懂了,
    =================================================================================================
    =================================================================================================
    =================================================================================================
    完整写好的是这样的:
    def auth(func):
    def inner():
    print ('before,验证') ====>在执行函数之前增加一个验证功能。
    func()
    print ('after,写日志') ====>在执行函数之后增加一个写日志功能。
    return inner
     
    @auth
    def f1():
    print 'f1' ========>连接数据库
    @auth
    def f2():
    print 'f2' ========>连接redis
    @auth
    def f3():
    print 'f3' ========>去硬盘拿数据
    。。。。。。。
     
     
    总结:
    第一步:先写一个嵌套函数,将需要增加的功能写在内层函数里
    第二步:在每个需要新增功能的函数上面加上装饰器即@auth
    ====================================================================================================
    ====================================================================================================
    ====================================================================================================
    装饰器去装饰含参数的函数:
    def auth(func): ====>装饰没有参数的函数
    def inner():
    print ('before,验证') ====>在执行函数之前增加一个验证功能。
    func()
    print ('after,写日志') ====>在执行函数之前增加一个写日志功能。
    return inner
     
     
     
    def auth_arg(func): ====>重新定义一个装饰器装饰有参数的函数
    def inner(arg):
    print ('before,验证') ====>在执行函数之前增加一个验证功能。
    func(arg)
    print ('after,写日志') ====>在执行函数之前增加一个写日志功能。
    return inner
     
     
    @auth
    def f1():
    print 'f1' ========>连接mysql
     
     
     
    @auth_arg
    def f4(arg): ========>连接oracle(带参数)
    print 'f4,arg'
     
    缺点:总结以上的方案我们发现,我没带参数写个装饰器,我带1个需要写个装饰器,带2个需要写个装饰器。。。。。。。
    完美解决方案就是利用万能动态参数,如下,这样不管你传不传参数,不管你传几个参数就都没有问题了。
    ------------------------------------------------------------------------------------------------------
    ------------------------------------------------------------------------------------------------------
    def auth(func):
    def inner(*args,**kwargs):
    print ('before,验证')
    func(*args,**kwargs)
    print ('after,写日志')
    return inner
     
     
    @auth
    def f1():
    print 'f1' ========>连接mysql
     
    @auth
    def f4(arg): ========>连接oracle(带1个参数)
    print 'f4,arg'
     
    @auth
    def f5(arg1,arg2,arg3,arg4): ========>连接redis(带4个参数)
    print 'f5,arg1,arg2,arg3,arg4'
     
    ==================================================================================================
    ==================================================================================================
    ==================================================================================================
    装饰器去装饰含返回值的函数:
    def auth(func):
    def inner(*args,**kwargs):
    print ('before,验证')
    temp = func(*args,**kwargs)
    print ('after,写日志')
    return temp
    return inner
     
     
    @auth
    def fetch_host_list(arg): =====>获取主机列表
    host_list = ['h1','h2','h3']
    return host_list
    =====================================================================================================
    =====================================================================================================
    =====================================================================================================
    装饰器实现登录验证原理(这个是装饰器应用最多的场景):
    def login():
    name = 'rooney'
    if name == 'rooney':
    return True
    else:
    return False
    def auth(func):
    def inner(*args,**kwargs):
    is_login = login()
    if not is_login:
    return "你输入的用户名不正确"
    temp = func(*args,**kwargs)
    print ('after,写日志')
    return temp
    return inner
     
     
    @auth
    def fetch_host_list(arg): =====>获取主机列表
    host_list = ['h1','h2','h3']
    return host_list
    =======================================================================================================
    =======================================================================================================
    =======================================================================================================
    装饰器实现token验证:
    def login(key):
    local = 'fdsareqwrwq12345d2srwq'
    if local == key:
    return True
    else:
    return False
    def auth(func):
    def inner(*args,**kwargs):
    #fetch_server_list('test',token=key) ====>业务线传了两个参数进来
    key = kwargs.pop('token')
    is_login = login(key)
    if not is_login:
    return "你输入的用户名不正确"
    temp = func(*args,**kwargs)
    print ('after,写日志')
    return temp
    return inner
     
     
    @auth
    def fetch_host_list(arg): =====>获取主机列表
    host_list = ['h1','h2','h3']
    return host_list
    ==========================================================================================================
    ==========================================================================================================
    ==========================================================================================================
    装饰器之多装饰器(盒子模型):
    def w1(func):
    def inner(*args,**kwargs):
    print ('w1,before')
    func(*args,**kwargs)
    print ('w1,after')
    return inner
     
     
    def w2(func):
    def inner(*args,**kwargs):
    print ('w2,before')
    func(*args,**kwargs)
    print ('w2,after')
    return inner
     
    @w2
    @w1
    def foo():
    print ('foo')
     
     
     
    foo()
     
     
    返回结果竟然是这样:
    w2,before
    w1,before
    foo
    w1,after
    w2,after
     
    套盒子,foo是一个盒子,上面加个w1装饰器就相当于外面又套了一层盒子,再加一个装饰器就相当于再套了个盒子,那么你打开的时候就是从外往里打开拿出来。
    =====================================================================================
    =====================================================================================
    =====================================================================================
    装饰器之装饰器加参数:
     
    #!/usr/bin/env python
    #coding:utf-8
     
    def Before(request,kargs):
    print 'before'
     
    def After(request,kargs):
    print 'after'
     
     
    def Filter(before_func,after_func):
    def outer(main_func):
    def wrapper(request,kargs):
     
    before_result = before_func(request,kargs)
    if(before_result != None):
    return before_result;
     
    main_result = main_func(request,kargs)
    if(main_result != None):
    return main_result;
     
    after_result = after_func(request,kargs)
    if(after_result != None):
    return after_result;
     
    return wrapper
    return outer
     
    @Filter(Before, After)
    def Index(request,kargs):
    print 'index'
     
    比如说:下面两个装饰器,一个带参数,一个不带参数
    @w1
    1.执行w1函数
    2.将w1函数的返回值赋值给被装饰器装饰的函数的函数名
    @w2
    1.执行w2函数,得到返回值,ret
    2.创建装饰器,@ + ret结合;@ret
    3.。。。。。。。
    1.执行ret函数
    2.将ret函数的返回值赋值给被装饰器装饰的函数的函数名
     
     
     
     
     
     
     
     
  • 相关阅读:
    支付方法及注意事项
    网站负载均衡策略
    工作成长
    java内存机制
    关于前途的一些思考
    git记录
    关于博客
    如何为公司创造价值?
    遍历集合方法总结
    二叉树和红黑二叉树
  • 原文地址:https://www.cnblogs.com/steven9898/p/11329419.html
Copyright © 2020-2023  润新知