Python之装饰器

功能:

为已存在的函数或对象添加额外的功能

 

原则:

  • 不改变源代码为其添加功能
  • 不改变函数的调用方式

 

方法:

装饰器 = 高阶函数 + 嵌套函数

(高阶函数:一个函数可以作为参数传递给另外一个函数,或者,一个函数的返回值是一个函数,即函数的入口地址)

  1. 函数名作为参数传递给装饰器(@decorator_name)
  2. 装饰函数返回函数名(函数地址)

注意:

  1. 默认情况下,装饰器会修改名字和文档说明,但是可以使用functools中 的@wraps()解决。@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
def decorator(func):
    """
    decorator __doc__
    """
    # @wraps(func)
    def wrapper(*args, **kwargs):
        """wrapper __doc__"""
        func()
    return wrapper


@decorator
def test():
    """test __doc__"""
    time.sleep(0.5)


test(1, 2)
print("function name:", test.__name__)
print("function doc :", test.__doc__)

# output:
# function name: wrapper
# function doc : wrapper __doc__

# 加了@wraps(func)后的output:
# function name: test
# function doc : test __doc__

 

 

例子:

1. 函数作为装饰器

此例子实现了一个计算调用函数所占用的时间

import time
from functools import wraps


def decorator(func):
    """
    function:decorator
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        """function:wrapper"""
        start = time.time()
        ret = func(*args, **kwargs)
        end = time.time()
        print("function {0} run time: {1}".format(func.__name__, end - start))
        # print("function {fun} run time: {time}".format(fun=func.__name__, time=end - start))
        return ret
    return wrapper


@decorator
def test(a, b, name="Lizo"):
    """function:test"""
    time.sleep(0.5)
    print(a, b, name)

2.类作为装饰器

为什么可以使用类作为装饰器?因为在Python中,一切皆对象,其实函数也是一个对象,如果一个类实现了 __call__(self)方法后,就可以像调用函数一样,直接加一个括号就可以调用。

class Runtime:
    def __init__(self):
        pass

    def __call__(self, func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time.time()
            ret = func(*args, **kwargs)
            end = time.time()
            print("function: {func} run time: {time}".format(func=func.__name__, time=end - start))
            return ret
        return wrapper


#使用装饰器方法1
runtime = Runtime()
@runtime
def test_class_decorator1():
    print("in the test_class_decorator")
    time.sleep(0.2)


#使用装饰器方法2
@Runtime()
def test_class_decorator2():
    print("in the test_class_decorator")
    time.sleep(0.2)

 

你可能感兴趣的:(python)