Python装饰器

装饰器

基本概念

  • python函数的装饰器其实就是一个函数,它接受一个函数作为参数并返回一个新的函数
  • python函数的装饰器仅会在函数被初始化的时候调用一次
  • functools库的wraps函数用来保留原始函数的重要元信息,使用装饰器时最好都添加该注解
  • 并不是所有的装饰器都使用了wraps函数,特别的,classmethodstaticmethod就没有遵守
  • 给类或静态方法提供装饰器时,需要确保装饰器在 @classmethod 或 @staticmethod 之前,即确保它们出现在装饰器的第一个位置

示例

示例1: 普通装饰器(计算函数执行时间)
# coding: utf-8

import typing
import functools
import time


def compute_time(func: typing.Callable):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print('time spend', end_time - start_time)
        return result

    return wrapper


@compute_time
def test1():
    for i in range(10):
        time.sleep(0.1)


def test2():
    for i in range(10):
        time.sleep(0.1)


if __name__ == '__main__':
# 以下两种运行方式,结果相同
    test1()
    compute_time(test2)()

执行结果

time spend 1.0140540599822998
time spend 1.0238919258117676
示例2: 带参数的装饰器(失败重试,限制最大重试次数)
# coding: utf-8

import functools


def retries(max_reties=2):
    def produce(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for i in range(max_reties):
                try:
                    print('produce num', i)
                    return func(*args, **kwargs)
                except Exception as e:
                    if i < (max_reties - 1):
                        continue
                    else:
                        raise e

        return wrapper

    return produce


@retries(3)
def ready():
    print('start to produce')
    raise Exception('error')


if __name__ == '__main__':
    try:
        ready()
    except Exception as e:
        print(e)

执行结果

produce num 0
start to produce
produce num 1
start to produce
produce num 2
start to produce
error
示例3:类的静态方法装饰器
# coding: utf-8

import functools
import time

import typing


def compute_time(func: typing.Callable):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print('time spend', end_time - start_time)
        return result

    return wrapper


class Calculator(object):
	
# 注意,如果以下两个装饰器的顺序错误,执行报错
    @staticmethod
    @compute_time
    def add(a: int, b: int) -> int:
        return a + b


if __name__ == '__main__':
    calculate_result = Calculator.add(1, 3)
    print(calculate_result)

执行结果

time spend 9.5367431640625e-07
4

python装饰器可以用来做很多事情,例如为被包装函数增加参数,扩充类的功能等等

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值