两个装饰器的执行顺序

两个装饰器的执行顺序

如下,两个装饰器time_func 和auth_func分别实现了测试程序耗时和认证功能

import time
user_name = "zb"
user_pwd = "123"

def time_func(func1):
    print("time")
    def inner1():
        print("from inner1")
        start_time = time.time()
        func1()
        stop_time = time.time()
        print(stop_time-start_time)
    return inner1

def auth_func(func2):
    print("auth")
    def inner2():
        print("from inner2")
        name = input("input your name:").strip()
        pwd = input("input your password:").strip()
        if name == user_name and pwd == user_pwd:
            print("login successful")
            func2()
        else:
            print("name or password error")
    return inner2
            
@time_func
@auth_func
def test():
    print("from test")    
test()

1.python解释器从上而下执行代码:导入时间模块,定义变量用户名和密码

2.遇到装饰器(闭包函数)time_func,申请了1片内存地址,函数名time_func指向了这片内存地址,程序继续向下执行(这里只是定义了函数,并不会执行,所以相当于1行代码)

3.遇到装饰器auth_func,这里同第2步,申请1片内存地址,函数名auth_func 指向这片内存地址,程序继续向下执行

4.解释器执行到装饰@time_func这里,此行代码下是一个装饰器@auth_func而不是一个函数,python解释器并不会执行装饰功能,程序继续向下执行

5.Python解释器执行到@auth_func,因为装饰的是一个函数test,定义test函数,申请一片内存地址,test指向它
1534663-20181119204902973-558431387.png

6.装饰器@auth_func 就相当于test = auth_func(test)

①执行等号左边代码:test赋值给func2即func2指向了test的内存地址

②auth_func():执行函数auth_func,定义了函数inner2,申请1片内存地址,函数名inner2指向这片内存地址(此处并未调用函数,故看成1行代码),继续向下执行,返回inner2

③test接收返回值inner2即test指向了inner2的内存地址
1534663-20181119204831862-1717581701.png

7.装饰器@time_func执行,test = time_func(test),

①test赋值给func1即func1指向test的内存地址(此时test指向了inner2),故func1指向了inner2,

②定义了函数inner1,申请1片内存地址,函数名inner1指向这片内存地址(未调用函数,故看成1行代码),继续向下执行,返回inner1

③test接收返回值inner1,test指向了inner1的内存地址
1534663-20181119204701177-426860724.png

8.调用函数test(),执行test指向的内存地址代码即inner1,inner1中的func1指向了inner2,inner2中的func2指向了test

inner1()

inner2()

test()

运行结果 inner1,inner2

实际运行结果如下,先装饰了auth_func,后装饰了time_func,先执行了计时功能,后执行了验证功能(此处特地延缓输入的时间,如果是先执行的验证功能,此处耗时应该很短)

1534663-20181119204456301-152792499.png

倒个顺序装饰:耗时0.0s极快

总结:1.靠近函数的先装饰

​ 2.先装饰的后执行

1534663-20181119204518773-492810889.png

转载于:https://www.cnblogs.com/robert-zhou/p/9985479.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想控制装饰器执行顺序来影响测试用例的行为,可以使用 `unittest` 模块提供的 `TestSuite` 类。你可以将测试用例添加到一个 `TestSuite` 对象中,并按照你希望它们执行的顺序添加装饰器。 例如,假设你有三个测试用例 `test_case1`、`test_case2` 和 `test_case3`,并且你希望它们按照以下顺序执行: 1. `test_case1` 2. `test_case2`,在运行之前需要先执行一个装饰器 `setup_test_case2` 3. `test_case3`,在运行之前需要先执行两个装饰器 `setup_test_case2` 和 `setup_test_case3` 你可以使用以下代码来实现: ```python import unittest class MyTestCase1(unittest.TestCase): def test_case1(self): # test code goes here class MyTestCase2(unittest.TestCase): def test_case2(self): # test code goes here def setUp(self): # setup code goes here def setup_test_case2(test_case): def wrapper(*args, **kwargs): test_case.setUp() # additional setup code goes here return test_case(*args, **kwargs) return wrapper class MyTestCase3(unittest.TestCase): def test_case3(self): # test code goes here def setUp(self): # setup code goes here def setup_test_case3(test_case): def wrapper(*args, **kwargs): test_case.setUp() # additional setup code goes here return test_case(*args, **kwargs) return wrapper # create a TestSuite object suite = unittest.TestSuite() # add test cases in the desired order suite.addTest(MyTestCase1('test_case1')) suite.addTest(MyTestCase2('test_case2')) suite.addTest(MyTestCase3('test_case3')) # add decorators to the test cases in the desired order suite._tests[1]._testMethodName = 'run_test_case2' suite._tests[1] = setup_test_case2(suite._tests[1]) suite._tests[2]._testMethodName = 'run_test_case3' suite._tests[2] = setup_test_case2(setup_test_case3(suite._tests[2])) # run the test suite unittest.TextTestRunner().run(suite) ``` 在上面的例子中,我们创建了一个 `TestSuite` 对象,并将测试用例 `MyTestCase1`、`MyTestCase2` 和 `MyTestCase3` 按照预期的顺序添加到 `TestSuite` 中。然后,我们使用 `_tests` 属性访问 `TestSuite` 中的测试用例,并在它们上面添加装饰器,以便它们以预期的顺序执行。 请注意,这种方法需要对 `unittest` 模块的内部实现有一定的了解,并且可能不太容易维护。因此,你应该仔细考虑是否真的需要这样做。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值