1--被装饰的函数不带参数
#"""无参数调用decorator声明时必须有一个参数,这个参数将接收要装饰的方法"""
def deco(func):#deco对func进行包装
... print 'start'
... func()
... print 'end'
... return func
...
>>> @deco
... def my():
... print 'is my'
...
start
is my
end
#注意:当使用上述方法定义一个decorator方法时,函数体内的额外操作只在被装饰的函数首次调用时执行,
>>> my()
is my
#如果要保证额外操作在每次调用被装饰的函数时都执行,需要换成如下的写法:
def deco(func):
... def wrapfunc():
... print 'start'
... func()
... print 'end'
... return wrapfunc
...
>>> @deco
... def myfunc():
... print 'is myfunc'
...
>>> myfunc()
start
is myfunc
end
2--被装饰函数带参数
def deco(func):
def newdeco(a, b):#被装饰函数的参数
print 'start'
ret = func(a, b)#func被装饰函数
print 'end'
return ret
return newdeco
>>>
>>> @deco
def myfunc(a, b):
res = a + b
print 'a + b = ',res
>>> myfunc(10, 20)
start
a + b = 30
end
3--被装饰函数,所带参数不确定
def deco(func):
def newdeco(*args, **kwargs):
print 'start'
print 'args = ',args
print 'kwargs = ', kwargs
res = func(*args, **kwargs)
print 'end'
return res
return newdeco
>>> @deco
def myfunc(a, b):#被装饰函数有两个参数
res = a + b
print "a + b = ", res
>>> myfunc(1, 1)
start
args = (1, 1)
kwargs = {}
a + b = 2
end
>>> @deco
def myfunc(a, b, c ):#3个参数
res = a + b + c
print "a + b +c = ", res
>>> myfunc(1, 2, 3)
start
args = (1, 2, 3)
kwargs = {}
a + b +c = 6
end
>>> @deco
def myfunc(*args,**kwargs):#参数是列表与字典
sum = 0
i = 0
for eachnum in args:
sum += eachnum
print 'args[%d] = %d' %(i, eachnum)
i += 1
print 'sum = ', sum
for eachkey in kwargs.keys():
print '%s = %s' % (eachkey, kwargs[eachkey])
>>> myfunc(1, 2, 3,lady = 'gaga',shakira = 'isabel')
start
args = (1, 2, 3)
kwargs = {'lady': 'gaga', 'shakira': 'isabel'}
args[0] = 1
args[1] = 2
args[2] = 3
sum = 6
lady = gaga
shakira = isabel
end
4--装饰器带参数
这个装饰器参数是包在被装饰函数的外面的
def deco(args):
def newdeco(func):
def wrapfunc():
print 'in wrapfunc start,args =',args
func()
print 'end ****'
return wrapfunc
return newdeco
>>> @deco("hello this is args of decorator")
def myfunc():print 'is myfunc'
>>> myfunc()
in wrapfunc start,args = hello this is args of decorator
is myfunc
end ****
5--装饰器带参数(参数为类)
>>> class locker:
def __init__(self):
print 'locker.__init__()'
@staticmethod#类的静态方法
def acquire():
print 'this is staticmethod method'
@staticmethod
def release():
print 'this is other staticmethod method'
>>> def deco(cls):
""" 装饰器的参数是个类,通过这个类,调用他的静态方法,装饰func()"""
def newdeco(func):
def wrapfunc():
print 'in wrapfunc'
cls.acquire()
try:
return func()
finally:
cls.release()
return wrapfunc
return newdeco
>>> @deco(locker)
def myfunc():print 'is myfunc'
>>> myfunc()
in wrapfunc
this is staticmethod method
is myfunc
this is other staticmethod method
6--用两个装饰器装饰函数
#!/usr/bin/env python
# -*- coding: cp936 -*-
""" This is decorator.py"""
class Father:
def __init__(self):
print 'is Father.__init__()'
@staticmethod
def acquire():
print 'is Father.acquire()'
@staticmethod
def unlock():
print 'is Father.unlock()'
class Sun(Father):#locker继承了myclass
def __init__(self):#如果不重写__init__(),locker会自动调用父类的init()方法
print 'is Sun.__init__()'
@staticmethod
def acquire():
print 'is Sun.acquire()'
@staticmethod
def unlock():
print 'is Sun.unlock()'
def deco(cls):#装饰函数的工具
def newdeco(func):#被装饰函数
def wrapfunc(*args, **kwargs):#被装饰函数的参数
print 'in wrapfunc start decorate'
cls.acquire()
try:
return func(*args, **kwargs)
finally:
cls.unlock()
return wrapfunc
return newdeco
class example:#不从任何父类继承 -- 经典类
@deco(Father)#选择mycalss当做装饰器函数
def myfunc1(self):
print 'in example is myfunc1()'
@deco(Father)
@deco(Sun)#用了两个装饰器
def myfunc2(self, a, b):
print 'in example is myfunc2()'
res = a + b
print 'a + b = ',res
def main():
a = example()
a.myfunc1()#myfunc1()输出被装饰的结果
print '*'*20
print a.myfunc1()
print '*'*20
a.myfunc2(1, 2)
if __name__ == '__main__':
main()
运行脚本 python decorator.py
输出如下
in wrapfunc start decorate
is Father.acquire()
in example is myfunc1()
is Father.unlock()
********************
in wrapfunc start decorate
is Father.acquire()
in example is myfunc1()
is Father.unlock()
None# 这个None -- print 会打印函数的返回值,函数没有返回值,所以打印None
********************
in wrapfunc start decorate#可以看出,装饰器的作用,先用调用Father装饰,所以Father这个装饰工具在最外层,里面的一层是Sun的装饰作用。离函数最近的装饰函数最先起作用,然后逐渐向外一层层的装饰
is Father.acquire()
in wrapfunc start decorate
is Sun.acquire()
in example is myfunc2()
a + b = 3
is Sun.unlock()
is Father.unlock()
7--装饰的函数有返回值
参考:
def deco(func):
def wrapfunc():
now = time()
func()
times = time() - now
return times
return wrapfunc
@deco
def my():
sum = 0
for i in range(100):
sum +=i
print 'sum = ',sum
return sum
>>> my()
sum = 4950
0.016000032424926758
>>> print my()
sum = 4950
0.0309998989105
>>> m = my()
sum = 4950
>>> m
0.015999794006347656
my()这个函数,是有返回值的,返回sum,但是由于没有在装饰器中返回这个sum,所以运行my()这个被装饰的函数后,找不到他本身的返回值了
可以在wrapfunc()中返回这个sum
>>> def deco(func):
def wrapfunc():
list = []#创建一个列表,存放多个返回值,或者返回一个字典,可以通过key来索引值,或者将返回值放在全局变量中
now = time()
res = func()
list.append(res)
times = time() - now
list.append(times)
return list
return wrapfunc
>>> @deco
def my():
sum = 0
for i in range(100):
sum +=i
print 'sum = ',sum
return sum
>>> my()
sum = 4950
[4950, 0.04699993133544922]
8--example--利用装饰器计算函数调用时间
有3个数学函数,比较用单线程运行这3个函数,用多线程运行这3个函数所用时间
#!/usr/bin/env python
# -*- coding: cp936 -*-
""" This is mtfacfib.py"""
from time import ctime, sleep, time
import threading
class MyThread (threading.Thread ):#线程类的子类
def __init__(self, func, args, name = ''):
threading.Thread.__init__(self)
= name
self.func = func
self.args = args
def getResult(self):
return self.res
def run(self):
print 'starting', self.func.__name__, 'at:',\
ctime()
#sleep(1)
self.res = apply(self.func, self.args)#func函数运行的结果
print self.func.__name__, 'finished at:',ctime()
""" This is the decorator"""
def deco(func):
def wrapfunc():
now = time()
func()
dict[func.__name__ + '_time'] = time() - now
#return dict
return wrapfunc
def fib(x):
sleep(0.005)
if x < 2:
return 1
return (fib(x - 2) + fib(x - 1))
def fac(x):
sleep(0.1)
if x < 2:return 1
return (x*fac(x-1))
def sum(x):
sleep(0.1)
if x < 2:return 1
return (x + sum(x-1))
""" data """
n = 12
dict = {}
ssum = 0
funcs = [fib, fac, sum]#list
nfuncs = range(len(funcs))
threads = []
@deco
def calculate_single():#统计单线程时间
for i in nfuncs:
print 'starting',funcs[i].__name__,'at:',\
ctime()
res = funcs[i](n)
print funcs[i].__name__, '=', res
print funcs[i].__name__,'finished at:',\
ctime()
#return res
@deco
def calculate_multiple():#统计多线程时间
for i in nfuncs:
threads[i].start()#启动线程
sleep(1)
for i in nfuncs:
threads[i].join()#等待线程结束
print funcs[i].__name__, '=', threads[i].getResult()
def main():
print '*** SINGLE THREAD***'
calculate_single()
print '\n*** MULTIPLE THREADS***'
for i in nfuncs:#创建线程,建立时挂起
t = MyThread(funcs[i], (n,), funcs[i])
threads.append(t)
calculate_multiple()
print '*'*10, 'all done', '*'*10
for i in dict.keys():
print i,'=', dict[i]
if dict['calculate_single_time'] > dict['calculate_multiple_time']:
print 'single time > multiple time'
else:
print 'single time < multiple time'
if __name__ == '__main__':
main()
运行结果 python mtfacfib.py
*** SINGLE THREAD***
starting fib at: Tue Sep 11 11:45:10 2012
fib = 233
fib finished at: Tue Sep 11 11:45:18 2012
starting fac at: Tue Sep 11 11:45:18 2012
fac = 479001600
fac finished at: Tue Sep 11 11:45:19 2012
starting sum at: Tue Sep 11 11:45:19 2012
sum = 78
sum finished at: Tue Sep 11 11:45:21 2012
*** MULTIPLE THREADS***
starting fib at: Tue Sep 11 11:45:21 2012
starting fac at: Tue Sep 11 11:45:22 2012
starting sum at: Tue Sep 11 11:45:23 2012
fac finished at: Tue Sep 11 11:45:23 2012
sum finished at: Tue Sep 11 11:45:24 2012
fib finished at: Tue Sep 11 11:45:28 2012
fib = 233
fac = 479001600
sum = 78
********** all done **********
calculate_single_time = 10.0780000687
calculate_multiple_time = 7.31299996376
single time > multiple time