python 装饰器
1 函数装饰器
构成:外部函数传入被装饰函数名,内部函数返回装饰函数名
特点:不修改函数的调用方式,不修改函数的代码
作用:在不对函数做任何修改的情况下增加额外的功能
例如:缓存装饰器,权限验证装饰器,日志装饰器,路由装饰器,异常处理装饰器,错误重试装饰器,计时装饰器等
函数装饰器装饰函数
import time def timmer(func): def wrapper(*args,**kwargs): start_time = time.time() res=func(*args,**kwargs) #如果被装饰函数有返回值,那么用res接收并return stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return res return wrapper @timmer def add(a,b): return a+b
print(add(1,2)) print(add.__name__) #返回wrapper,被装饰的函数已经不再是它本身了 add=timmer(add),timmer方法返回的就是wrapper函数
函数装饰器装饰类
def Single(cls): clses = {} def single(*args, **kwargs): if cls not in clses: clses[cls] = cls(*args, **kwargs) return clses[cls] return single @Single class Food: def __init__(self,name): self.name = name a = Food('红薯') b = Food('萝卜') print(a==b)# True print(a is b)# True print(Food.__name__)#single,原理同上
函数装饰器的执行过程,我们修改一下示例1 。
def timmer(func): print('外部函数 功能1') def wrapper(*args,**kwargs): print('内部函数 功能1') res=func(*args,**kwargs) print('内部函数 功能2') return res print('外部函数 功能2') return wrapper @timmer def add(a,b): return a+b
#直接运行代码,结果:
外部函数 功能1
外部函数 功能2 可以看出在我们没有调用add方法的时候print已经生效了,这更说明被装饰的函数已经不再是他本身了
add(2,3)
外部函数 功能1
外部函数 功能2
内部函数 功能1
内部函数 功能2 综合两个结果可以看出是先执行外部函数,返回内部函数wrapper,然后执行wrapper
再看一个例子:
def timmerA(func): print('A外部函数 功能1') def wrapperA(*args,**kwargs): print('A内部函数 功能1') res=func(*args,**kwargs) print('A内部函数 功能2') return res print('A外部函数 功能2') return wrapperA def timmerB(func): print('B外部函数 功能1') def wrapperB(*args,**kwargs): print('B内部函数 功能1') res=func(*args,**kwargs) print('B内部函数 功能2') return res print('B外部函数 功能2') return wrapperB @timmerB @timmerA def add(a,b): return a+b print(add(1,2))
结果如下:
A外部函数 功能1
A外部函数 功能2 #先运行A装饰器外部函数
B外部函数 功能1 #然后运行B装饰器外部函数
B外部函数 功能2
B内部函数 功能1 #此时根据我们上个示例,应该运行被装饰函数,此时 add = wrapperB(wrapperA(add)) 这样应该就比较好理解了
A内部函数 功能1
A内部函数 功能2
B内部函数 功能2
2 类装饰器
类装饰器主要是通过类的__call__方法来实现的
类装饰器装饰函数
class Foo(object): def __init__(self, func): self._func = func
def __call__(self): print('class decorator runing') self._func() print('class decorator ending') @Foo def bar(): print('bar') bar() print(bar.__name__) #报错,'Foo' object has no attribute '__name__'
#举个例子
class A:
def __init__(self):
pass
a = A()
print(a.__name__) # A instance has no attribute '__name__'
类装饰器装饰类
class Foo(object): def __init__(self, cls): self.cls = cls def __call__(self,name): s = self.cls(name) s.color = '红色' return s @Foo class Food: def __init__(self,name): self.name = name a = Food('红薯') print(a.name) print(a.color) print(Food.__name__)