关于python 装饰器

深碍√TFBOYSˉ_ 2022-05-19 12:06 199阅读 0赞

关于装饰器

无参装饰器

普通函数

  1. def say_hello(*args, **kwargs):
  2. print 'hello world'

无参装饰器

  1. def debug(func): # debug为装饰器,func为要被装饰的函数
  2. def wrapper(*args, **kwargs):
  3. # 此处的args,kwargs承接func函数的参数,使用wrapper替换func
  4. # 装饰器最内层的函数为被装饰函数的替换函数,参数列表必须和被装饰函数相同
  5. print "[DEBUG]: enter {}()".format(func.__name__)
  6. return func(*args, **kwargs) # 调用被装饰的func函数
  7. return wrapper

装饰器调用,原始方法

  1. say_hello = debug(say_hello) # 添加功能并保持原函数名不变

等价于 语法糖 方式调用

  1. @debug
  2. def say_hello():
  3. print "hello!"

对于有参装饰器

  1. def debug(flag):
  2. # 通过语法糖方式 @debug(flag=True)调用后才获取到了wrapper函数,然后才是使用wrapper再次装饰(无参形式)func函数
  3. def wrapper(func):
  4. def inner(*args,**kwargs):
  5. print "[DEBUG]: enter {}()".format(func.__name__)
  6. return func(*args, **kwargs)
  7. return inner
  8. return wrapper

语法糖 方式调用

  1. @debug(flag=True)
  2. def say_hello():
  3. print "hello!"

等价于

  1. wrapper = debug(flag=True) # wrapper 是一个函数
  2. say_hello = wrapper(say_hello) # wrapper相当 debug(say_hello)的功能

类方法的函数装饰器

类方法的函数装饰器和函数的函数装饰器类似

对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数inner也要传入一个类实例的参数,其他的用法都和函数装饰器相同。
如:

  1. def debug(flag):
  2. def wrapper(func):
  3. def inner(instance, *args, **kwargs): # 类方法的函数装饰器的装饰函数参数列表必须和被装饰的函数一样,故第一个参数必须为等同于类方法的self的类实例
  4. print "[DEBUG]: enter {}()".format(func.__name__)
  5. return func(instance, *args, **kwargs)
  6. return inner
  7. return wrapper

装饰:

  1. class Method(object):
  2. @debug(flag=False)
  3. def func(self, args, kwargs):
  4. time.sleep(0.8)

functools.wraps()函数

打印装饰后的 say_hello 函数的 __name__

  1. print(say_hello.__name__)

输出: inner

造成被装饰函数自身的信息丢失,可以使用functools.wraps()解决该问题

  1. from functools import wraps
  2. def debug(flag):
  3. def wrapper(func):
  4. @wraps(func)
  5. def inner( *args, **kwargs):
  6. print "[DEBUG]: enter {}()".format(func.__name__)
  7. return func(*args, **kwargs)
  8. return inner
  9. return wrapper
  10. print(say_hello.__name__)

输出: say_hello

装饰器调用顺序

无参装饰器

  1. def dec1(func):
  2. print "AAAAA"
  3. def inner(*args, **kwargs):
  4. print "BBBBB"
  5. func(*args, **kwargs)
  6. return inner
  7. def dec2(func):
  8. print "CCCCC"
  9. def inner(*args, **kwargs):
  10. print "DDDDD"
  11. func(*args, **kwargs)
  12. return inner
  13. @dec1
  14. @dec2
  15. def test():
  16. pass
  17. test()

输出为:

  1. CCCCC
  2. AAAAA
  3. BBBBB
  4. DDDDD

因为等价于

  1. test = dec2(test) # 输出 CCCCC
  2. test = dec1(test) # 输出 AAAAA
  3. test() # 输出BBBBB DDDDD

带参装饰器

  1. def dec1(*args):
  2. print "11111"
  3. def wrapper(func):
  4. print "AAAAA"
  5. def inner(*args, **kwargs):
  6. print "BBBBB"
  7. func(*args, **kwargs)
  8. return inner
  9. return wrapper
  10. def dec2(*args):
  11. print "22222"
  12. def wrapper(func):
  13. print "CCCCC"
  14. def inner(*args, **kwargs):
  15. print "DDDDD"
  16. func(*args, **kwargs)
  17. return inner
  18. return wrapper
  19. @dec1()
  20. @dec2()
  21. def test():
  22. pass
  23. test()

输出为:

  1. 11111
  2. 22222
  3. CCCCC
  4. AAAAA
  5. BBBBBB
  6. DDDDD

因为等价于

  1. wrapper1 = dec1() # 输出 11111
  2. wrapper2 = dec2() # 输出 22222
  3. # 类似无参的情况
  4. @wrapper1
  5. @wrapper2
  6. def test():
  7. pass
  8. test() # 输出 CCCCC AAAAA BBBBBB DDDDD

发表评论

表情:
评论列表 (有 0 条评论,199人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Python装饰

    装饰器 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:

    相关 [Python]装饰

    > Python中利用@符号可以很容易实现函数装饰器的功能,本文就这些用法做一些简单的总结。 介绍 Python中由于函数本身也可以当作变量来使用,因此可以直接将函数作

    相关 python装饰

    装饰器,人如其名,就是给成添加附功能的手段,但是该代码已经上线或已经被使用,那么就不能大批量的修改源代码,这样是不科学的也是不现实的,因为就产生了装饰器,使得其满足下面两点:

    相关 python装饰

    1. 闭包函数   在看装饰器之前,我们先来搞清楚什么是闭包函数。python是一种面向对象的编程语言,在python中一切皆对象,这样就使得变量所拥有的属性,函数也同样拥

    相关 python装饰

    Python2.4开始提供装饰器(decorator),适当使用装饰器可以有效提高代码可读性和可维护性。装饰器的本质就是一个函数,这个函数接受其他函数作为参数,并将其以一个新的

    相关 python 装饰

    装饰器介绍 装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。在Python中,我们有多种方法对函数和类进行加工,比如在P