详解 python 各种装饰器的实现

本贴最后更新于 1294 天前,其中的信息可能已经东海扬尘

1、普通装饰器

接下来我们来看一个普通的装饰器函数

def decorator(fun): def func_w(): print('---装饰器扩展的新功能') fun() return func_w @decorator def func_demo(a,b): res = a/b print('a除B的结果为:',res) # @decorator这是样的写法是python中的一个语法糖, #它的一个等同所有就是原来的这句 @decorator=====》func_demo= decorator(func_demo)

**装饰器原理阐述:**将被装饰的函数当做一个参数传到装饰器中,并且让被装饰的函数名指向装饰器内部的函数,在装饰器的内部函数中用接收到的参数再调用被装饰的函数。

**案列、**使用装饰器来统计函数运行的时间

import time def decorator(func): def fun(): strat_time = time.time() #获取开始时的时间 func() #运行被装饰的函数 end_time = time.time() # 获取结束时的时间 t_time = end_time - strat_time #算出运行总时间 print('运行总时间%s'%t_time) #打印运行总时间 return fun @decorator def work(): time.sleep(2) print('原来函数的功能代码') work()

2、装饰带参数的函数

def decorator(func): def fun(a,b): print('-----装饰器实现的功能-------')) func(a,b) return fun @decorator def func(a,b): print("----执行函数--func-----") print(a+b)

3、通用装饰器

def decorator(func): def fun(*args,**kwargs): print('-----执行装饰器实现的功能-------') func(*args,**kwargs) return fun @decorator def func(a,b,f): print("----执行函数--func-----") print(a+b+f) func(10,20,30)

4、装饰器装饰类

装饰器装饰类本质上和装饰函数没有区别,同样是把被装饰的类和函数当成参数传入装饰器中,把返回的结果传递给原来定义的类去接收。就是说装饰完之后,原来定义的类名,指向的就是装饰器内部的嵌套函数了。

def decorator(func): def fun(*args,**kwargs): print('-----执行装饰器实现的功能-------') return func(*args,**kwargs) return fun @decorator # @decorator 等同于 Hero = decorator(Hero) class Hero(object): def __init__(self,name,age): self.name=name self.age=age print('正在初始化') def move(self): print('%s在快速移动'%self.name) laoli = Hero('老李',19)

使用类装饰器的时候,记得要返回被装饰的类调用的结果,

5、装饰器传参数

前面介绍的几种装饰器在使用的时候不需要传递参数,那么如果在装饰器的时候需要传参数该怎么去实现呢?

# 定义可以传参的装饰器 def musen(name, age): def decoreter(func): def wrapper(*args, **kwargs): print("装饰器传递的参数name:", name) print("装饰器传递的参数age:", age) func(*args, **kwargs) return wrapper return decoreter # 使用装饰器并传参 @musen('木森',18) def work(): print('原功能函数的代码') # 代码解析:上面装饰的哪一行代码,的效果等同于work = musen('木森',18)(work) # 意思就是先调用musen('木森',18) 使用调用的结果去装饰work,然后再把结果赋值给work

总结:

6、类实现装饰器

前面我们是用闭包函数来实现的装饰器,那么接下来给大家扩展一下,使用类来当做一个装饰器来用

class Test(object): def __init__(self,func): self.func = func def __call__(self, *args, **kwargs): print('这个是类装饰器') self.func(*args,**kwargs) #说明: #1. 当用Test来装作装饰器对func函数进行装饰的时候,首先会创建Test的实例对象,并且会把func这个函数名当做参数传递到__init__方法中,即在__init__方法中的func变量指向了func函数体 #2. func函数相当于指向了用Test创建出来的实例对象 #3. 当在使用func()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法 #4. 为了能够在__call__方法中调用原来func指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用,所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到func之前的函数体
回帖
请输入回帖内容 ...