一、装饰器
定义:修改其他函数功能的函数
意义:让其他函数在不修改任何代码的前提下增加其他额外的功能(比如手机壳,在不修改手机的情况下,增加手机的美观。颜色等)。不用装饰器的函数是永久性的修改,用了装饰器是函数可随时修改
举例1:
def add(a,b): return a + b def new_add(add,*args,**kwargs): return f'<{add(*args, **kwargs)}>' if __name__ == '__main__': print(f'<{add(1,1)}>') #没有装饰器new_add时 <2> print(new_add(add, 1, 1)) #使用装饰器时 <2>
举例2:
def text(): return "Hello world" def add_itali(func): def wrapper(): return f"<i>{func()}<i>" return wrapper if __name__ == '__main__': print(add_itali(text)()) #结果: <i>Hello world<i>
使用注解符是装饰器使用更加方便:
# 先定义装饰器 def add_itali(func): def wrapper(): return f"<i>{func()}<i>" return wrapper #使用 @装饰器函数名 方式 @add_itali def text(): return "Hello world" if __name__ == '__main__': print(text()) # <i>Hello world<i>
多个装饰器时,可在函数上加多个装饰符
def add_itali(func): '''加粗''' def wrapper(): return f"<i>{func()}<i>" return wrapper def add_bold(func): '''倾斜''' def wrapper(): return f"<b>{func()}<b>" return wrapper @add_itali @add_bold def text(): return "Hello world" if __name__ == '__main__': print(text()) # <i><b>Hello world<b><i>
注意:调换@add_itali @add_bold的位置,查看结果:<b><i>Hello world<i><b>
举例3:
import logging import time def log(func): def wrapper(*args, **kwargs): logging.info(f'{func.__name__} is running....') return func(*args, **kwargs) return wrapper def calc_time(func): def wrapper(*args, **kwargs): start = time.time() func(*args, **kwargs) end = time.time() print(f'{func.__name__} 运行了{end-start}时间') return func(*args, **kwargs) return wrapper @log @calc_time def add(a,b): return a + b if __name__ == '__main__': add(1, 3)
装饰器格式:
装饰器就是一个函数
def 装饰器名(func): def wrapper(*args, **kwargs): //要做的装饰,此处省略若干代码 return func(*args, **kwargs) return wrapper
二、类的装饰器
作用:用来装饰类
def 装饰器名(cls): //装饰代码若干 return cls
举例1:
def add_name(cls): cls.name = "zjx" return cls @add_name class A(object): pass if __name__ == '__main__': a = A() print(a.name) #结果: zjx
三、装饰器类
这个装饰器不是一个函数,而是一个类
格式如下:
class 装饰器名(object): def __init__(self,func): self.func = func def __call__(self, *args, **kwargs): pass # 写装饰代码 return self.func(*args, **kwargs)
_ _call_ _方法:函数的调用,实际就是调用函数里的_ _call_ _方法
举例:
class A(object): def __init__(self,func): self.func = func def __call__(self, *args, **kwargs): print("call is running.....") result = self.func(*args, **kwargs) return result @A def add(a,b): return a + b if __name__ == '__main__': print(add(1,3))
''' call is running..... 4 '''
注意:调用类的对象,__call__会自动被调用
四、带参数的装饰器
如:@log(filename='text.log')
# 带参数的装饰器-三层函数(最外层用来传参)---装饰器里面可以传参数 # @log(filename = "123.txt") import logging def add_log(filename): # 最外层:接收装饰参数 def inner(func): # 中间层:接收被装饰函数 def wrapper(*args, **kwargs): # 内层装饰函数:接收被装饰的函数的参数 logging.warning(f"{func.__name__}函数正在被调用...") result = func(*args, **kwargs) # 调用被装饰函数 return result # 把被装饰的函数的运行结果返回 return wrapper return inner @add_log(filename="123.txt") def add(a, b): return a + b if __name__ == '__main__': print(add(3,4)) """ WARNING:root:add函数正在被调用... 7 """