装饰器

装饰器

例子

def w1(func):
  def inner():
    print("---正在验证权限---")
    if False:
      func()
     else:
      print("没有权限")
     return inner
  
#f1 = w1(f1)
@w1
def f1():
  print("---f1---")
  
@w1
def f2():
  print("---f1---")
  
f1()
f2()

以上例子中,@w1就是语法糖,等价于f1 = w1(f1)

注意,解释器在遇到@w1的时候就已经开始装饰了,不是在调用的时候才进行装饰。后面调用 f1() 函数只是把装饰的结果返回而已。
----------------------------------------------------------------------------------

def w1(func):
  def inner():
    print("---正在验证权限---")
    if False:
      func()
    else:
      print("没有权限")
  return inner
  
def f1():
  print("---f1---")
  
def f2():
  print("---f1---")
  
f1 = w1(f1)
f1()
f2 = w1(f2)
f2()

这块代码和上面那块等价。

执行过程:

第16行之前:
装饰器

执行 右半部分  w1(f1)  之后:****装饰器

执行左边赋值  f1 = w1(f1)
装饰器

由于蓝色块的代码内存被占用,无法丢弃,所以当执行f2=w1(f2)的时候,会开辟一片新的蓝色块内存,进行与上述同样的操作

#定义函数:完成包裹数据
def makeBold(fn):
  def wrapped():
    print("----1----")
    return "<b>" + fn() + "</b>"
  return wrapped

#定义函数:完成包裹数据
def makeItalic(fn):
  def wrapped():
    print("----2----")
    return "<i>" + fn() + "</i>"
  return wrapped

@makeBold  				# test3 = makeBold(test3)
@makeItalic				# test3 = makeItalic(test3)
def test3():
  print("----3----")
  return "hello world-3"

ret = test3()
print(ret)

执行结果与调用过程:
装饰器

多个装饰器的装饰和解装执行过程:

装饰器

输出结果是:
装饰器

通用装饰器:

def func(functionName):
  def func_in(*args,**kwargs):
    print("----记录日志----")
    ret = functionName(*args,**kwargs)
    return ret
  return func_in

@func
def test():    					#对不带参数、有返回值的函数进行装饰
  print("----test----")
  return "haha"

@func					
def test2():						#对不带参数、无返回值的函数进行装饰
  print("----test2----")

@func
def test3(a):						#对带参数、无返回值的函数进行装饰
  print("----test3--a=%d--"%a)
  
ret = test()
print("test return value is %s"%ret)

a = test2()
print("test2 return value is %s"%a)

test3(11)

执行结果:
装饰器
**

带有参数的装饰器:

def func_arg(arg):
  def func(functionName):
    def func_in():
      print("---记录日志-arg=%s---"%arg)
      if arg=="heihei":
        functionName()
        functionName()
       else:
        functionName()
     return func_in
  return fun

#1. 先执行func_arg("heihei")函数,这个函数return 的结果是func这个函数的引用
#2. @func
#3. 使用@func对test进行装饰
@func_arg("heihei")
def test():
  print("---test---")
  
#带有参数的装饰器,能够起到在运行时,有不同的功能
@func_arg("haha")
def test2():
  print("---test2---")
  
test()
test2()
     

类装饰器:

class Test(object):
  def __init__(self,func):
    print("---初始化---")
    print("func name is %s"%func.__name__)
    self.__func = func
  def __call__(self):
    print("---装饰器中的功能---")
    self.__func()

@Test
def test():
  print("---test---")

# 执行test()
test()

执行过程:
装饰器

关键点:

  1. test变量想要调用类,则要在类里面写__call__(self),之后调用变量test()的时候则会调用__call__(self)方法。
  2. @Test 在进行装饰的时候就已经调用了__init__()方法了。原因是@Test 等价于 test = Test(test)

函数装饰器和类装饰器的区别:

函数装饰器是:有一个函数A,再定义另外一个新函数B,然后让新函数B里面有一个变量指向函数A,然后让函数A的名字指向新函数B
类装饰器: 让A函数名指向一个对象,这个对象里面有个属性指向原来的函数A