python--装饰器

 

装饰器:对函数的包装

 

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--装饰的函数有返回值

参考:http://www.cnblogs.com/Jerry-Chou/archive/2012/05/23/2515004.html

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)
        self.name = 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

 

 

 

posted on 2012-09-11 11:47  龙沙宝石  阅读(365)  评论(0编辑  收藏  举报

导航