python每日习题:自己封装失败重跑装饰器

Posted 七月的小尾巴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python每日习题:自己封装失败重跑装饰器相关的知识,希望对你有一定的参考价值。

题目

实现一个重运行的装饰器,可以用来装饰任何一个功能函数,只要被装饰的函数执行出现AssertionError,
则重新执行该函数,同一个函数最多重运行三次。

下面讲一下小余在做这道题的心里历程,从昨天下班的时候,看到这道题目做起来真的很上头,一直写到晚上一点钟。


当我第一次看到这倒题目的时候,想到的就是递归调用实现

def test_run(func):
    def swapper(a, b, count=0):
        try:
            func(a, b)

        except AssertionError:
            if count < 3:
                print("断言失败,开始尝试失败重跑,当前尝试第{}次重跑".format(count+1))
                swapper(a, b, count+1)

    return swapper


@test_run
def test(a, b):
    assert a == b

写的时候很快,但是当我重新看题目的时候,突然发现题目中的关键字, 可以用来装饰任何一个功能函数,突然发现,我直接用 a,b形参了。于是又重新整理了一下思路:

写的飞快,但是执行的时候,发现了这种思路并不可行,从debug中,我们可以看到,实参中10,直接作为count被传了,导致再if条件判断下并没有执行这行代码。

于是又换了一种思路,count的值,作为装饰器参数传递:

本来一开始想的是,装饰器传递参数,然后去更改装饰器的值,判断失败重跑,但是抛了一个语法错误。嵌套函数里面仿佛是无法更改外层的函数值内容。(这里有厉害的宝子,可以一起沟通哦~已经涉及到小余的知识盲区了)

最后改来改去,改成了下面的方法实现:

def test_assert(func):

    def swapper(*args, **kwargs):
        # 执行函数,判断如果函数执行失败,return "AssertionError"
        def start_func(*args, **kwargs):
            try:
                func(*args, **kwargs)
            except AssertionError:
                return "AssertionError"

        count = 0
        # 调用函数
        res = start_func(*args, **kwargs)
        # 判断当函数出现异常并且异常次数小于 3 次
        if res == "AssertionError":
            if count <= 3:
                for i in range(3):
                    print("断言失败,开始尝试失败重跑,当前尝试第{}次重跑".format(i))
                    # 失败重跑
                    a = start_func(*args, **kwargs)
                    count += 1
                    # 当用例执行通过,则直接退出
                    if a != "AssertionError":
                        break
            else:
                pass

    return swapper

但是写完之后,我总觉得功能虽然实现了,但是整体的写法上面,并不是我想要的效果,那么我们来看看终极版:

def decorator(func):
    def wrapper(*args, **kwargs):
        for i in range(4):
            try:
                res = func(*args, **kwargs)
            except AssertionError as e:
                # 判断当用例执行到第三次的时候,抛异常
                if i == 3:
                    raise e
            else:
                # 执行通过,直接返回函数内容
                return res

    return wrapper


@decorator
def test(a, b):
    print("这里是函数内容")
    assert a == b

以上是关于python每日习题:自己封装失败重跑装饰器的主要内容,如果未能解决你的问题,请参考以下文章

python 基础

解决报错:在Python中使用property装饰器时,出现错误:TypeError: descriptor ‘setter‘ requires a ‘property‘ object but(代码片

Python关于装饰器的练习题

python3练习-装饰器

Python__装饰器练习题

Python__装饰器练习题