Python decorator装饰器
来源:互联网 发布:淘宝捉猫猫是干嘛的 编辑:程序博客网 时间:2024/06/03 19:01
瞥一眼装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
装饰器模式介绍
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。何时使用:在不想增加很多子类的情况下扩展类。如何解决:将具体功能职责划分,同时继承装饰者模式。关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。应用实例: 1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。缺点:多层装饰比较复杂。使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。注意事项:可代替继承。
什么是Python装饰器
Python装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
下面我们以一个示例来一步步深入解释Python装饰器
1.我们来获得一个程序的大概执行时间
我们可以直接把计时逻辑方法”myfunc”内部,但是这样的话,如果要给另一个函数计时,就需要重复计时的逻辑。所以比较好的做法是把计时逻辑放到另一个函数中
import timedef dec(func): start=time.time() func() end=time.time() passedtime=(end-start)*1000 print(passedtime)def myfunc(): print("function start") time.sleep(1) print("end of function")dec(myfunc)myfunc()
运行结果:
function startend of function1000.0154972076416function startend of function
但是,上面的做法也有一个问题,就是所有的myfunc调用处都要改为dec(myfunc)
2.下面,做一些改动,来避免计时功能对myfunc函数调用代码的影响
import timedef dec(func): def wrapper(): start=time.time() func() end=time.time() passedtime=(end-start)*1000 print(passedtime) return wrapperdef myfunc(): print("function start") time.sleep(1) print("end of function")print("funciton name is: ",myfunc.__name__) myfunc=dec(myfunc) print("funciton name is: ",myfunc.__name__)myfunc()
运行结果
funciton name is: myfuncfunciton name is: wrapperfunction startend of function1000.0152587890625
经过了上面的改动后,一个比较完整的装饰器dec就实现了,装饰器没有影响原来的函数,以及函数调用的代码。例子中值得注意的地方是,Python中一切都是对象,函数也是,所以代码中改变了myfunc对应的函数对象。
3.装饰器语法糖
在Python中,可以使用”@”语法糖来精简装饰器的代码:
import timedef dec(func): def wrapper(): start=time.time() func() end=time.time() passedtime=(end-start)*1000 print(passedtime) return wrapper@decdef myfunc(): print("function start") time.sleep(1) print("end of function")print("funciton name is: ",myfunc.__name__) myfunc()
运行结果
funciton name is: wrapperfunction startend of function1000.0152587890625
使用了”@”语法糖后,我们就不需要额外代码来给myfunc重新赋值了,其实@dec的本质就是myfunc = dec(myfunc),当认清了这一点后,后面看带参数的装饰器就简单了。
被装饰的函数带参数
对于被装饰函数需要支持参数的情况,我们只要使装饰器的内嵌函数支持同样的签名即可。比如我们的函数是function(a,b),则装饰器就需要改为同样的格式,参数名字可以不一样:wrapper(aa,bb)这里还有一个问题,如果多个函数拥有不同的参数形式,怎么共用同样的装饰器?在Python中,函数可以支持(*args, **kwargs)可变参数,所以装饰器可以通过可变参数形式来实现内嵌函数的签名。
带参数的装饰器
装饰器本身也可以支持参数,例如说可以通过装饰器的参数来禁止计时功能通过例子可以看到,如果装饰器本身需要支持参数,那么装饰器就需要多一层的内嵌函数。
装饰器调用顺序
装饰器是可以叠加使用的,那么这是就涉及到装饰器调用顺序了。对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。
@a@b@cdef f ():
等效于
f = a(b(c(f)))
Python内置装饰器
在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。
- staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
- classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
- property 是属性的意思,表示可以通过通过类实例直接访问的信息
在Python装饰器中其实涉及到了一个很重要的函数思想‘闭包’,为了更好的理解装饰器,建议大家去学习了解一下闭包。
或者说等我出一博客来介绍一下,等某天吧。
- Python Decorator(装饰器)
- python decorator(装饰器)
- Python 装饰器/Decorator
- Python decorator(装饰器)
- 装饰器 decorator (python)
- Python装饰器 Decorator
- python 装饰器 decorator
- 【Python】装饰器 - Decorator
- python decorator装饰器
- python装饰器(decorator)
- Python 装饰器decorator
- python-装饰器Decorator
- Python Decorator装饰器
- python--装饰器(decorator)
- Python decorator装饰器
- Python 装饰器 decorator
- Python 装饰器(Decorator)
- python中的装饰器decorator
- 图像处理中傅里叶变换以及频率域图像增强详解
- void 0 的理解
- 拒绝了对对象 'user' (数据库 '****',架构 'dbo')的 SELECT 权限
- netease YunXin
- Angular入门之环境搭建(VS code)
- Python decorator装饰器
- Radar Installation POJ
- MySQL buffer pool中的三种链
- 评分法模型开发-WOE值计算
- 判断进程是否正常退出
- 第三章 修改数据库为mysql并初始化
- 合并石子(动态规划经典题)
- [PAT乙级]1017. A除以B (20)
- Vue指令总结