python 类修饰器

1. 修改类函数。

场景: 如果要给一个类的所有方法加上计时,并打印出来。demo如下:

# -*- coding:utf-8 -*-
import time
def time_it(fn):
    "Example of a method decorator"
    def decorator(*args, **kwargs):
    t1=time.time()
        ret = fn(*args, **kwargs)
    print '		%d seconds taken for %s'%(time.time()-t1, fn.__name__)
    return ret

    return decorator

def class_decorator(*method_names):
    def class_rebuilder(cls):
        "The class decorator example"
        class NewClass(cls):
            "This is the overwritten class"
            def __getattribute__(self, attr_name):
                attr_val = super(NewClass, self).__getattribute__(attr_name)
                if callable(attr_val) and attr_name in method_names:
                    return time_it(attr_val)
                return attr_val

        return NewClass
    return class_rebuilder

@class_decorator('first_method', 'second_method')
class MySecondClass(object):
    """
    This class is decorated
    """
    def first_method(self, *args, **kwargs):
        print "	this is a the MySecondClass.first_method"
    time.sleep(2)

    def second_method(self, *args, **kwargs):
        print "	this is the MySecondClass.second_method"
    time.sleep(1)

if __name__ == "__main__":
    print "::: With a decorated class :::"
    z = MySecondClass()
    z.first_method()
    z.second_method()

好处相比函数修饰器要稍微简洁一点(在类有很多方法时)

2. 增加类成员

场景:比如统一给所有的模型增加id, created_time属性

# -*- coding:utf-8 -*-
def addAttrs(*attrs):
    def re_build(cls):
        class newClass(cls):
            def __init__(self,*args, **kws):
                for attr in attrs:
            setattr(self, attr, None)
                self.__id = id
                super(newClass, self).__init__(*args, **kws)
        return newClass
    return re_build

@addAttrs('id', 'created_time')
class DBModelOne(object):
    def __init__(self, *args, **kwargs):
        pass

if __name__=='__main__':
    m = DBModelOne(5)
    print m.id, m.created_time

or

# -*- coding:utf-8 -*-
import time
def cd(cls):
    def init(*args, **kwargs):
        cls_obj = cls(*args, **kwargs)
        setattr(cls_obj, 'id', time.time())
        return cls_obj
    return init
@cd
class A(object):
    def __init__(self, name, age, sex='f'):
        self.name=name
        self.age=age
        self.sex=sex
    def s(self):
        print self.id

if __name__=='__main__':
    print type(A)#<type 'function'>
    a=A('Alice', 22)
    print type(a)#<class '__main__.A'>
    print a#<__main__.A object at 0x7fe617baa690>
    print a.name, a.age, a.sex#Alice 22 f
    a.s()

转载请注明来自:http://www.cnblogs.com/Tommy-Yu/p/5457751.html

原文地址:https://www.cnblogs.com/Tommy-Yu/p/5457751.html