zoukankan      html  css  js  c++  java
  • 装饰器

    就是把自己定义的函数装饰一遍,在原来函数的基础上做些其他操作,然后返回一个新的函数,调用名称是一样的,只是内容稍有变化(注意是新的,已经不是本来定义的函数了,但是原来的函数最终还是会在装饰器最内层返回的,只是返回时添加了些东西,比如逻辑判断,打印,往哪个列表添加东西等等操作,比如在原来函数功能的基础上,判断是否登录,是否是VIp,再执行该函数)

    装饰函数无参数

    可以看出调用decorator函数,返回的是wrapper函数对象,而不是abc这个函数对象,
    abc这个函数在wrapper中已经是被调用了的,只是返回一个结果。以上代码的运行结果如下图,可以看出装饰

    #装饰函数无参数
    def decorator(foo):
        def wrapper():
            print('wrapper')
            return foo()
        return wrapper
    
    #自定义函数
    def abc():
        print ('abc')
    
    #装饰函数abc,使之函数abc()运行时,提前print('wrapper')
    abc = decorator(abc)   #  abc = wrapper
    abc()       #  wrapper      abc
    print(abc())      #  wrapper      abc  None
    

    python的装饰器语法就是自动调用decorator函数,并以自定义的函数abc函数对象为参数,返回wrapper函数对象,这样一个过程。
      切记 : 回调函数不可以使用装饰器,如果非要使用那就把这个回调函数名再赋值一个新名字,用新名字的函数去装饰

    def decorator(foo):
        def wrapper():
            print ('@wrapper')
            return foo()
        return wrapper
    
    @decorator # @相当于abc = decorator(abc),只是他在定义定义其他函数时就把那个函数装饰了,把函数名作为装饰器的参数
    def abc():
        print ('abc')
    abc()   #   @wrapper         abc
    print(abc())      #   @wrapper   abc   None
    

    带参数的装饰器:

    接下来,再深一步来说说带参数的装饰器, 其实这个只比上面那个无参数装饰器多了一步,就是先调用装饰器函数,再返回真正的装饰器,之后的步骤和无参数的一样了,说得太抽象?
    直接上代码,这样就明显了,先调用用最外层的函数,返回的是一个真正的装饰器,然后像之前无参数的时候一样,修饰abc函数后返回新的函数对象

    def decoratorFunc(arg):
        def decorator(foo):
            def wrapper():
                if arg == 0:
                    print('lalala')
                return foo()
            return wrapper
        return decorator
    
    deco0 = decoratorFunc(0)     #   deco0 = decorator  带有暂时不用的参数0     return decorator
    deco1 = decoratorFunc(1)     #   deco1 = decorator     带有暂时不用的参数1     return decorator
    def abc():
        print('abc')
    abc0 = deco0(abc)      #    abc0 = decorator(abc)   return wrapper
    abc1 = deco1(abc)      #    abc1 = decorator(abc)   return wrapper
    abc0()     #lalala    abc
    abc1()      # abc
    
    @decoratorFunc(0)
    def abc():
         print ('abc')
    abc1()      # abc
    
    输出:
    lalala
    abc
    abc
    abc
    
    

    写更普通的装饰器,如果被装饰的函数有参数怎么办?很简单,利用python的可变长度参数就行。
    注意,是在wrapper这个函数上我们写上python的可变长度参数,而装饰器函数decorator的参数永远只有一个,就是函数对象。看以下代码,是无参数装饰器的例子,
    如果是带参数的函数,也只需要把wrapper改成接收可变长度参数就行

    def decorator(foo):
        def wrapper(*args, **kwargs):
            print ('wrapper')
            return foo(*args, **kwargs)
        return wrapper
    @decorator
    def abc(arg):
        print ('abc:', arg)
    
    abc('你好啊')     #wrapper        abc: 你好啊
    
    写入自己的博客中才能记得长久
  • 相关阅读:
    File类总结
    MyBatis框架一级缓存与二级缓存
    SpringMVC运行原理总结
    SpringMVC:详述拦截器
    SpringMVC:自定义视图及其执行过程
    详述ThreadLocal
    浅析MVC中的数据流动
    error: gpg failed to sign the data 的一个解决办法
    保险业务核心系统设计参考
    奇怪的404
  • 原文地址:https://www.cnblogs.com/heris/p/11444613.html
Copyright © 2011-2022 走看看