一、装饰器是什么
在代码运行期间不改变原函数定义的基础上,动态给该函数增加功能的方式,称之为装饰器。是一个很著名的设计模式
二、装饰器的使用范围
较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概况的讲,装饰器就是为已有的函数添加额外的功能。
三、装饰器和闭包
另外装饰器其实是个闭包,闭包就是:如果一个函数定义在另一函数的作用域内容,并且引用外层函数的变量,则该函数称为闭包。装饰器其实就是把一个函数作为参数后返回一个替代版的函数
装饰器的具体定义:
1、把要装饰的方法作为输入参数;
2、在函数体内可以进行任意的操作
3、只要确保最后返回一个可执行的函数即可(可以是原来输入的参数函数,也可以是一个新函数)
四、装饰器分类
无参数decorator:生成一个新的装饰器函数
有参数decorator:装饰函数先处理参数,再生成一个新的装饰器函数,然后对函数进行装饰
无参装饰器
#coding:utf-8
__author__ = 'sunjinjuan'
def log(fun):
def wapper(*args,**karg):
print "before %s called." %fun.__name__
ret=fun(*args,**karg)
print "after %s called" %fun.__name__
return ret
return wapper
@log
def myfunc(a,b):
print "myfunc(%s,%s) called" %(a,b)
return a+b
@log
def myfunc1(a,b,c):
print "myfunc1(%s,%s,%s) called" %(a,b,c)
return a+b+c
print myfunc(2,3)
print myfunc(4,5)
print myfunc1("a",'b','c')
print myfunc1("dd","ff","gg")
执行结果:
D:\software\python27\python.exe D:/untitled/oopObject/test9.py
before myfunc called.
myfunc(2,3) called
after myfunc called
5
before myfunc called.
myfunc(4,5) called
after myfunc called
9
before myfunc1 called.
myfunc1(a,b,c) called
after myfunc1 called
abc
before myfunc1 called.
myfunc1(dd,ff,gg) called
after myfunc1 called
ddffgg
有参装饰器
#coding:utf-8
__author__ = 'sunjinjuan'
def log(arg):
def _log(fun):
def _log(*args,**kwargs):
print "before %s is called" %fun.__name__
print "now params is%s" %arg
ret=fun(*args,**kwargs)
print "after %s is called" %fun.__name__
return ret
return _log
return _log
@log("myfun1")
def fun1(a,b):
print "fun1 is called"
return a+b
@log("myfun2")
def fun2(a,b,c):
print "fun2 is called"
return a+b+c
print fun1(2,3)
print fun1(5,6)
print fun2('a','b','c')
print fun2("hello"," world","!")
执行结果:
D:\software\python27\python.exe D:/untitled/oopObject/test10.py
before fun1 is called
now params ismyfun1
fun1 is called
after fun1 is called
5
before fun1 is called
now params ismyfun1
fun1 is called
after fun1 is called
11
before fun2 is called
now params ismyfun2
fun2 is called
after fun2 is called
abc
before fun2 is called
now params ismyfun2
fun2 is called
after fun2 is called
hello world!
带类参数的装饰器
mylocker.py文件内容:
#coding:utf-8
__author__ = 'sunjinjuan'
class mylocker(object):
def __init__(self,a,b):
self.a=a;
self.b=b
@staticmethod
def access():
print "mylocker access is called"
@staticmethod
def release():
print "mylocker release is called"
class lockerex(object):
@staticmethod
def access():
print "lockerex access is called"
@staticmethod
def release():
print "lockerex release is called"
def doc(cls):
def _doc(fun):
def _doc(*args,**kwargs):
print "before %s called" %(fun.__name__)
cls.access()
try:
ret=fun(*args,**kwargs)
finally:
cls.release()
print "after %s called" %(fun.__name__)
return ret
return _doc
return _doc
test11.py文件内容:
#coding:utf-8
__author__ = 'sunjinjuan'
from mylocker import *
@doc(mylocker)
def fun1(a,b):
print "fun1 is called"
return a+b
@doc(lockerex)
@doc(mylocker)
def fun2(a,b,c):
print "fun2 is called"
return a+b+c
if __name__== "__main__":
print fun1(1,2)
print fun1(3,4)
print fun2('a','b','c')
print fun2('aa','bb','cc')
执行结果:
D:\software\python27\python.exe D:/untitled/oopObject/test11.py
before fun1 called
mylocker access is called
fun1 is called
mylocker release is called
after fun1 called
3
before fun1 called
mylocker access is called
fun1 is called
mylocker release is called
after fun1 called
7
before _doc called
lockerex access is called
before fun2 called
mylocker access is called
fun2 is called
mylocker release is called
after fun2 called
lockerex release is called
after _doc called
abc
before _doc called
lockerex access is called
before fun2 called
mylocker access is called
fun2 is called
mylocker release is called
after fun2 called
lockerex release is called
after _doc called
aabbcc
五、内置装饰器
staticmethod:定义实例方法为静态方法
classmethod:定义实例方法为类方法
property:对类属性的操作.以下是property装饰器的使用方法
(1)property方法,实现对属性变量的封装:
#coding:utf-8
__author__ = 'sunjinjuan'
class Person(object):
def __init__(self,name):
self.__name=name;
def get_name(self):
return self.__name
def set_name(self,name):
print(u"当前调用函数setName()")
self.__name=name
def del_name(self):
print("remove...")
del self.__name
name=property(get_name,set_name,del_name,"name property docs")
bob=Person("bob")
print(bob.name)
bob.set_name("joe")
print(bob.name)
bob.del_name()
print(bob.name)
执行结果如下:
(2)property装饰器
以下代码设置了birth是读写权限,age变量是只读权限
#coding:utf-8
__author__ = 'sunjinjuan'
import datetime
class Student(object):
@property
def birth(self):
return self._birth;
@birth.setter
def birth(self, birth):
self._birth=datetime.datetime.strptime(birth,'%Y-%m-%d')
print(u"设置学生出生时间:%s" %(self._birth))
@property
def age(self):
currentTime=datetime.datetime.now()
currentDate=currentTime.strftime("%Y-%m-%m")
timedelta=datetime.datetime.strptime(currentDate,'%Y-%m-%d')-self._birth
return timedelta.days/365
s=Student()
s.birth="1999-01-01"
print s.birth
print u"学生当前年龄为:%s" %s.age
执行结果:
六、装饰器的顺序
代码示例:
@A
@B
@C
def f():
pass
等价于:f=A(B(C(f)))