Python之装饰器

功能:

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

 

原则:

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

 

方法:

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

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

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

注意:

  1. 默认情况下,装饰器会修改名字和文档说明,但是可以使用functools中 的@wraps()解决。@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
  2. 装饰器作用于函数上,但是如果装饰器装饰在一个类上面,相当于为类中的所有方法都加上了装饰器
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)
class Runtime:
    def __init__(self, func):
        self.func = func

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

@Runtime
def test_class_decorator1():
    print("in the test_class_decorator")
    time.sleep(0.2)

 

3.带参数的装饰器

如果需要装饰器接收参数,则需要添加一层函数

import time
from functools import wraps

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

@decorator(a=1)
def test(a, b, name="Lizo"):
    pass

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值