• Python decorator


    在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)

    本质上,decorator就是一个返回函数的高阶函数,它可以让函数在不变动任何代码的前提下增加额外功能。装饰器的返回值也是函数。它经常用于:插入日志,性能测试,事务处理,缓存,权限校验等场景。有了装饰器我们就可以抽离出大量与函数功能本身无关的代码并继续重用。概括的讲,装饰器就是为已经存在的对象添加额外的功能。

    下面的例子是在调用函数f前后增加打印日志的功能

    #!python2
    #-*- coding:utf-8 -*-
    
    
    
    def f():
        print "Call function f"
        
    f1=f
    f1()
    
    #查看函数对象的名字
    f.__name__
    f1.__name__
    
    #导入functools模块
    #因为经过装饰的函数它们的__name__变成了decorator里面的函数名字,对于
    #这个例子就是write_ahead
    #为了把原始函数名字等属性复制到write_ahead中我们使用@functools.wraps(func)
    #这样就可以避免类似write_ahead.__name__ = func.__name__的代码
    
    
    import functools
    
    #定义一个decorator,接受函数f为参数
    
    def log(func):
        @functools.wraps(func)
        def write_ahead(*args,**kw):
            print "Will Call %s" % f.__name__
            func(*args,**kw)
            print "After call func:"
            
        return write_ahead
    
    #用@把decorator置于函数f定义处
    
    @log
    def f():
        print "Call function f"
    
    f1=f
    f.__name__
    f1.__name__
    
    #调用函数f不仅会调用f本身还会在其前后打印log
    #相当于 f=log(f)
    
    f1()
    
    
    
    #下面是接受参数的decorator写法
    
    
    import functools
    
    def log(text):
        def decorator(func):
            @functools.wraps(func)
            def write_ahead(*args,**kw):
                print "Will Call %s with %s" % (f.__name__,text)
                func(*args,**kw)
                print "After call func:"
            return write_ahead
        return decorator
    
    @log("sss")
    def f():
        print "Call function f"
    
    f1=f
    f.__name__
    f1.__name__
    f1()
    
    
    
    #把以上俩种整合
    
    def log(obj):
        
        if isinstance(obj,str):
            
            text=obj
            
            def decorator(func):
                @functools.wraps(func)
                def write_ahead(*args,**kw):
                    print "Will Call %s with %s" % (f.__name__,text)
                    func(*args,**kw)
                    print "After call func:"
                return write_ahead
            return decorator
        
        else:
            
            func=obj
            @functools.wraps(func)
            def write_ahead(*args,**kw):
                print "Will Call %s" % f.__name__
                func(*args,**kw)
                print "After call func:"
            return write_ahead
            
    @log
    def f():
        print "Call function f"
    
    f1=f
    f.__name__
    f1.__name__
    f1()
    
    
    @log("sss")
    def f():
        print "Call function f"
    
    f1=f
    f.__name__
    f1.__name__
    f1()
    #class decorator
    
    class c_d(object):
        def __init__(self,func):
            self._func=func
            
        def __call__(self):
            print "class decorator is running"
            self._func()
            print "class decorator is ending"
            
    @c_d
    
    def test():
        print "call test func"
        
    test()
    #装饰器顺序
    
    @a
    @b
    @c
    
    def f():
        
    等价于
    
    f=a(b(c(f)))
    #装饰器带类参数
    
    class locker:
        def __init__(self):
            print("locker.__init__() should be not called.")
             
        @staticmethod
        def acquire():
            print("locker.acquire() called.(这是静态方法)")
             
        @staticmethod
        def release():
            print("  locker.release() called.(不需要对象实例)")
     
    def deco(cls):
        '''cls 必须实现acquire和release静态方法'''
        def _deco(func):
            def __deco():
                print("before %s called [%s]." % (func.__name__, cls))
                cls.acquire()
                try:
                    return func()
                finally:
                    cls.release()
            return __deco
        return _deco
     
    @deco(locker)
    def myfunc():
        print(" myfunc() called.")
     
    myfunc()
    myfunc()
    class mylocker:
        def __init__(self):
            print("mylocker.__init__() called.")
             
        @staticmethod
        def acquire():
            print("mylocker.acquire() called.")
             
        @staticmethod
        def unlock():
            print("  mylocker.unlock() called.")
     
    class lockerex(mylocker):
        @staticmethod
        def acquire():
            print("lockerex.acquire() called.")
             
        @staticmethod
        def unlock():
            print("  lockerex.unlock() called.")
     
    def lockhelper(cls):
        '''cls 必须实现acquire和release静态方法'''
        def _deco(func):
            def __deco(*args, **kwargs):
                print("before %s called." % func.__name__)
                cls.acquire()
                try:
                    return func(*args, **kwargs)
                finally:
                    cls.unlock()
            return __deco
        return _deco
        
        
    class example:
        @lockhelper(mylocker)
        def myfunc(self):
            print(" myfunc() called.")
     
        @lockhelper(mylocker)
        @lockhelper(lockerex)
        def myfunc2(self, a, b):
            print(" myfunc2() called.")
            return a + b
     
    if __name__=="__main__":
        a = example()
        a.myfunc()
        print(a.myfunc())
        print(a.myfunc2(1, 2))
        print(a.myfunc2(3, 4))
        

    下面的例子也不错

    http://www.cnblogs.com/SeasonLee/archive/2010/04/24/1719444.html

  • 相关阅读:
    学习的成本
    .Net Framework Client Profile 和 .Net Framework的区别[转]
    惆怅的开始
    Android Json解析
    android键盘的Done按钮
    百度地图SDK v2.1.2使用方法
    使用百度地图SDK 这是之前版本 现在的sdk v2-1-2使用方法完全改变
    svn
    Android 图片相关
    Android开发 开启闪光灯 关键代码
  • 原文地址:https://www.cnblogs.com/dadadechengzi/p/6514632.html
Copyright © 2020-2023  润新知