美文网首页
类装饰器,装饰函数或者类 方法

类装饰器,装饰函数或者类 方法

作者: 伍只蚊 | 来源:发表于2018-02-17 21:47 被阅读437次

装饰器类,通用于 function 或 class method
参考: https://stackoverflow.com/questions/1288498/using-the-same-decorator-with-arguments-with-functions-and-methods

先贴上代码,后面会有一点解析:

import functools
import time
import logging

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

class call_logger(object):
    """
    Decorator class to log calls on functions or class methods,
    e.g..
        @call_logger
        def my_function():
       class MyClass(object):         
            @call_logger
            def my_method(self):
    """
    def __init__(self, func):
        self._func = func 
        self._wrapped = None
        self._obj = None

    def __call__(self, *args, **kwags):
        if not self._wrapped:
            if self._obj:
                self._wrapped = self._wrap_method(self._func)
                self._wrapped = functools.partial(self._wrapped, self._obj)
            else:
                self._wrapped = self._wrap_function(self._func)
        return self._wrapped(*args, **kwags)

    def __get__(self, obj, type=None):
        self._obj = obj
        return self

    def _wrap_function(self, function):
        """
        Perform the decorator wrapping for a regular function.
        """
        @functools.wraps(function)
        def inner(*args, **kwags):
            """
            Implementation of the wraped function.
            """
            started = time.time()
            exc_name = None
            result = None
            try:
                result = function(*args, **kwags)
            except Exception as ex:
                exc_name = type(ex).__name__
                raise
            finally:
                _log_it(started, function, result, exc_name)
            return result
        return inner

    def _wrap_method(self, method):
        """
        Perform the decorator wrapping for a class method.
        """
        def inner(self, *args, **kwags):
            """
            Implementation of the wrapped function.
            """
            started = time.time()
            exc_name = None
            result = None
            try:
                result = method(self, *args, **kwags)
            except Exception as ex:
                exc_name = type(ex).__name__
                raise
            finally:
                _log_it(started, method, result, exc_name)
        return inner


def _log_it(started, method, result, exc_name):
    finished = time.time()
    elapsed = (finished - started) * 1000
    modname, methname = _get_caller_info(method)
    logging.debug("%s %s takes %s ms", modname, methname, elapsed)


def _get_caller_info(method):
    modname = method.__module__
    methname = method.__name__
    return modname, methname

@call_logger
def test():
    print 'test function'
    time.sleep(1)
    return True

class MyClass(object):

    @call_logger
    def test_method(self):
        time.sleep(1)
        print "test method"

if __name__ == "__main__":
    test()
    test_obj = MyClass()
    test_obj.test_method()
  1. 初始化时先将 目标函数储存到装饰器实例的私有属性 _func中,这时还没有进行装饰。

2 . call 方法的调用实际完场了装饰和执行函数两个部分。

  1. get 方法是装饰通用类方法的关键
    当装饰器装饰上 test_method时,此时的test_method指向的call_logger的实例对象。然后通过test_obj.test_method 时就触发了 get方法,
    传入test_obj对象,赋给_obj属性,返回call_logger自身的对象。接着()直接触发call方法,装饰和执行目标方法。

  2. 在_wrap_method中,注意inner函数第一个参数要传入self,因为装饰的是实例方法,实例方法的第一个参数为实例本身。通过偏函数来设置第一个默认参数为self._obj

github:
https://github.com/qq915522927/python_enhance/

相关文章

  • 类装饰器,装饰函数或者类 方法

    装饰器类,通用于 function 或 class method参考: https://stackoverflow...

  • 装饰器(Decorator)

    装饰器(Decorator) 装饰器是一种函数,写成@ + 函数名。它可以放在类和类方法的定义前面。 类上的装饰 ...

  • Python装饰器类的使用——bound/unbound met

    引言 在学习装饰器类方法时发现,如果装饰器类只有__ call __方法则只能装饰普通的函数(function),...

  • typescript 五种装饰器

    装饰器类型 装饰器的类型有:类装饰器、访问器装饰器、属性装饰器、方法装饰器、参数装饰器,但是没有函数装饰器(fun...

  • 装饰器

    装饰器有点像高阶函数;一个函数返回另一个函数; 装饰器是一个函数;用在类、类的属性、类的方法、类方法的参数上;功能...

  • TS装饰器

    一:类的装饰器:是一种与类(class)相关的语法,用来注释或修改类和类方法,装饰器本身是一个函数,装饰器通过@来...

  • 记录两个装饰器

    统计函数被调用次数的装饰器 类中的某个方法用于装饰类中的其他方法

  • decorator

    装饰器 装饰类对象@testclass A{}function test(target){//类对象装饰器函数ta...

  • 装饰器

    装饰器 decorator类装饰器 带参数的装饰器 举例(装饰器函数;装饰器类;有参与无参) https://fo...

  • 装饰器4

    装饰器装饰类 使用类装饰器的时候,记得要返回被装饰的类调用的结果装饰器函数 再 init 之前执行 例子1:给类添...

网友评论

      本文标题:类装饰器,装饰函数或者类 方法

      本文链接:https://www.haomeiwen.com/subject/bulvtftx.html