装饰器功能强大,如何运行呢,本文以函数装饰器来说明下
1、定义
def wrap(f):
    return f #此处返回函数

@wrap
def func(a:int,b:str):
    pass

注意和@wrap ()比较,后面这个形式是装饰器本身传参数时候用。实际是wrap()(func)()多层而已
后面详解。

2、调用
func(a:int,b:str)

调用时候发生了什么?
首先调用wrap 返回一个函数(注意,函数类装饰器,必须最终返回函数)
在调用返回的函数。    可理解为:wrap(func)(2,"ff")
所以最终调用还是按照原被装饰函数形式进行,比如参数限制。


上面装饰器很简单,限制了参数,若写个灵活的,可装饰任意函数(带任意参数的,变参形式)如何?
一般因为被装饰函数参数固定,如何不固定呢?想到了 args kwargs
也就是重写个函数改变原先调用时候规定参数的限制。如下

点击(此处)折叠或打开

  1. def wrap2(f):
  2.     def iner(*args,**kwargs): #用args kwargs,iner函数替换原先函数的固定参数约定,可接受任意形式参数。
  3.         return f(*args,**kwargs) #根据实际传入参数,在装饰器内部调用被装饰函数。
  4.     return iner

  5. @wrap2
  6. def func2(a,b,c): #3个参数的
  7.     pass
  8. func2("a",2,4)

  9. @wrap2
  10. def func2(a):#1个参数的
  11.     pass
  12. func2("a")

以上是2个不同函数 func1,func2.  
这个wrap2装饰器,返回的是iner函数,不再是原f函数,该iner函数可接受任意参数。接受任意参数后,f函数在装饰器内部进行调用 :f(*args,**kwargs)  (根据原函数实际参数进行)
通过这种装换具有很大灵活性。理解重要一点是:该装饰器返回的是什么函数


有时候,希望装饰器本身也要参数 ,增强多样性。如何操作?
很简单

点击(此处)折叠或打开

  1. def wrap2(arg:str): #第一层传递装饰器参数
  2.     print(hello)
  3.     def decordator(f): #第二层 定义:传递被装饰函数
  4.         def iner(*args,**kwargs): #第3层,定义:替换原先被装饰函数,改变参数约定
  5.             return f(*args,**kwargs) #最终在装饰内调用被装饰函数
  6.         return iner # 返回第三层(最后一层),以备按照iner函数形式(变参形式)进行调用
  7.     return decordator 对应返回第二层函数,用于下次传入被装饰函数

  8. @wrap2("hello")
  9. def test(a):
  10.     pass


  11. 调用
  12. test("aaa")
调用可理解如下
wrap2("hello")(test)("aaa")

12-16 16:09