美文网首页
Python中的Decorator: 两种使用场景

Python中的Decorator: 两种使用场景

作者: zeks有好的生物钟 | 来源:发表于2018-11-10 17:17 被阅读7次

    使用 Python 中的Decorator完成以下功能, 代码均是在Python 3.6下编写:

    1. 记录函数调用时参数的 Log 工具
    2. 函数调用计数器.

    分别使用 函数装饰器类装饰器 完成.

    log 工具

    创建一个 函数装饰器, 该装饰器的作用是输出其所wrap函数的函数名与参数, 很多时候可以作为日志工具, 追踪代码执行轨迹.

    创建函数装饰器

        def log_func(func):
            def _wrapper(*args, **kwargs):
                print('Execute {} with args: {}, {}'.format(func.__name__, args, kwargs))
                return func(*args, **kwargs)
        return _wrapper
    

    创建函数并使用装饰器

        @log_func
        def add(x, y, z):
            return x + y + z
    

    在控制台调用函数, 检查控制台输出

        if __name__ == "__main__":
            a = add(2,3, z=5)
            print(a)
    

    输出结果为

        Execute add() with args: (2, 3), {'z': 5}
        10
    

    函数调用技术器

    这是Python官方列出的装饰器的一种用法, 见页面PythonDecoratorLibrary#Counting_function_calls.

    创建类装饰器, 该装饰器负责将wrap的函数, 存储在类的静态列表里, 并暴露两个静态方法, 用于显示单个函数或所有函数的调用次数统计情况.

    创建类装饰器

        class countcalls(object):
           "Decorator that keeps track of the number of times a function is called."
           __instances = {}
           
            def __init__(self, f):
                self.__f = f
                self.__numcalls = 0
                countcalls.__instances[f] = self
    
           def __call__(self, *args, **kwargs):
              self.__numcalls += 1
              return self.__f(*args, **kwargs)
    
           @staticmethod
           def count(f):
              "Return the number of times the function f was called."
              return countcalls.__instances[f].__numcalls
    
           @staticmethod
           def counts():
              "Return a dict of {function: # of calls} for all registered functions."
              return dict([(f, countcalls.count(f)) for f in countcalls.__instances])
    

    装饰器类countcalls, 拥有一个class level 变量 __instances = {}, 相当于是Java里的静态变量. 该变量用于存储所有函数的调用次数统计, key为函数对象, value为该函数对象所初始化出的countcalls的实例.

    countcalls类的实例拥有一个实例变量 self.__numcalls, 并且会在装饰器被调用的时候更新数值. 即在 __call__()函数中更新.

    创建函数并使用类装饰器countcalls

        @countcalls
        def add(x, y):
            return x + y
    
        @countcalls
        def sub(x, y):
            return x - y
    

    调用函数, 并通过countcalls的静态方法查看调用统计

        if __name__ == "__main__":
            print(add(2, 3))
            print(add(10,23))
            print(sub(5, 6))
    
            counts = countcalls.counts()
            print(counts)
    

    输出结果

        5
        33
        -1
        {<function add at 0x000002856EC11E18>: 2, <function sub at 0x000002857076CA60>: 1}

    相关文章

      网友评论

          本文标题:Python中的Decorator: 两种使用场景

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