我又回来了,深夜更文,神情仓促。。。最近在华为做openstack相关的一些项目,顺便进修了一下Python知识,看到装饰器这一块时懵懂极了,网上找的大概都是例子,经过仔细研究揣摩,总结出了装饰器使用的本质规则,以备后查,希望对Python装饰器有疑问的朋友有帮助。
首先要理解Python具备的这几个特性:
1、用类对象调用一个方法,方法的第一个实参self就是对象本身,如果方法不是通过类对象调用,则self实参是你显式传的参数,例如通过装饰器的方式传递,正是本文要 解释的
这里的几处方法的调用都是通过对象的形式调用的,所以self形参就是调用者
2、任何对象都可以当作方法,比如类本身是一个方法,对象也是一个方法,方法更是一个方法
为什么类是方法:比如有一个类Cls,如果我们这样用Cls(),那么会默认调用构造函数__init__()
为什么对象是方法:比如obj=Cls(),那么我们这样用obj(),则默认会调用Cls类里的__call__方法,当然__call__必须手动实现,美其名曰这个类实现了callable接口。
为什么方法是方法这个就不用解释了,地球人都明白
好了,接下来看看什么是装饰器吧,我们直接看跨类装饰
1、首先让我们看看如何用一个类的方法装饰另一个类中的方法
一、用Deco.dec来装饰myFunc,实际上是把myFunc作为参数传递给了Deco.dec方法,并返回另一个方法extendFunc
使得以后调用myFunc的地方会转调用extendFunc
二、由于装饰器语法的限制,用 Deco.dec装饰myFunc时必须用Deco类来引用(Deco.dec是通过类引用方法)
因此注定了dec方法为类方法
三、必须返回一个方法,这是装饰器的约定,否则在调用myFunc的时候就不知道调什么方法了
四、调用了myFunc的地方就转而调用extendFunc,所以在执行extendFunc的时候第一个实参是mycls
五、必须至少保留一个形参,因为你不知道调用者会传什么参数,所以我们这里可以使用可变参数*arg1和**arg2
六、被装饰的方法变成了普通方法,而装饰的方法则替代了被装饰的方法
七、被装饰的方法由于没有经过对象引用,直接传入装饰器,变成了普通方法,所以self形参变成了普通参数
之前我们用方法类装饰方法,我们现在用类来装饰方法(其实也是用方法装饰方法,因为类也是方法,请记住刚才的特性之一)
好了,最后进阶看一下下面这个案例