• python-装饰器


     使用实例:

    背景:测试过程中,遇到这样一种情况,A接口请求后需要等待几秒再执行B接口请求,可以给B加个装饰器实现此功能,让B每次请求时先等待几秒。

    example1:

    import time
    def wait(func):
        # func(*args, **kw)可以使函数适配任意多的参数
        def wrapper(*args, **kw):
            time.sleep(3)
            return func(*args, **kw)
    
        return wrapper

    class Template: @wait def get_opt_auditresult(self, engineid, type): # time.sleep(4) @wait实现了该功能 url = '' if type == 1: url = self.conf.get('auditcenter', 'address') + '/api/v1/opt/all /auditResultList/' + str(engineid) return self.get(url) # 调用 from common.template_2_x import Template from config.read_config import ReadConfig import unittest import warnings class TestDelete(unittest.TestCase): def setUp(self): warnings.simplefilter("ignore", ResourceWarning) self.tem = Template() def test_opt_07(self): '''审核通过,医生修改处方''' engineid = self.tem.get_opt_engineid('opt','处方一',1) # 审核打回 self.tem.opt_audit(engineid,0) self.tem.send_data('opt','修改处方一1',**self.tem.change_data) # 只修改处方头 res = self.tem.get_opt_auditresult(engineid,1) self.assertEqual(2,res['data'][0]['rejectStatus']) if __name__ == '__main__': unittest.main()

     实例代码地址:传送门

    example2:

    def dec(f):
        n = 3
        def wrapper(*args,**kw):
            return f(*args,**kw) * n
        return wrapper
    
    @dec
    def foo(n):
        return n * 2
    
    foo(2)
    
    相当于:
    def dec(f):
        n = 3
        def wrapper(*args,**kw):
            return f(*args,**kw) * n
        return wrapper
    
    
    def foo(n):
        return n * 2
    
    foo=dec(foo)
    foo(2)
    code

    简言之,foo(2)=wrapper(2)=foo(2)*3=2*2*3=12

    装饰器理论介绍

    装饰器是什么:

    装饰器是为已经存在的函数或者对象添加额外的功能。本质上是一个闭包函数(闭包函数:本质是个嵌套函数,内层函数引用外层函数的变量,外层函数返回内层函数)

    装饰器的作用:

    1.不修改已有函数的源代码

    2.不修改已有函数的调用方式

    3.为已有函数添加额外的功能

    格式一:有参数

    @decorator(arg1, arg2)    
    def fun():
        pass
    
    等价于:
    def fun():
        pass
    fun = decorator(arg1, arg2)(fun)

    格式二:无参数

    import time
    from functools import wraps


    def timethis(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
    start = time.time()
    result = func(*args, **kwargs)
    end = time.time()
    print(func.__name__, end - start)
    return result

    return wrapper


    @timethis
    def conutdown(n):
    while n > 0:
    n -= 1
    """
    @timethis
    def conutdown(n):
    while n > 0:
    n -= 1
    等价于 conutdown = timethis(conutdown) 该装饰器代码本身就会运行,而不是等到conutdown(10000)才执行,理解不了的话,在@timethis处打个断点debug一下就知道怎么执行的了
    执行过程为:
    调用timethis,返回wrapper,且conutdown指向wrapper,所以后面执行conutdown(10000)就相当与执行wrapper(10000)
    """

    conutdown(10000)
    print(conutdown.__name__)
    输出结果为:

      conutdown 0.015621423721313477
      conutdown      # 注意红色字体@wraps(fun1)是为了避免被装饰函数自身的信息丢失,如果注释@wraps(fun1),该输出结果将会是wrapper,故任何时候定义装饰器的时候,都应该使用 functools 库中的 @wraps 装饰器来注解底层包装函数

    格式三:有多个装饰器

    @decotator_one
    @decorator_two
    def fun():
     pass
    
    等价于:
    def fun():
     pass
    fun = decorator_one(decorator_two(fun) 

    三大内置装饰器(@staticmethod、@classmethod、@property)

    静态方法:是类中的方法,不需要实例。 需要通过修饰器 @staticmethod 来进⾏修饰,静态⽅法不需要多定义参数

    • 特性:静态方法不能使用类变量和实例变量
    • 调用方式:一般通过类名调用

    类方法:是类对象所拥有的⽅法,需要⽤修饰器 @classmethod 来标识其为类⽅法,对于类⽅法,第⼀个参数必须是类对象,⼀般以 cls 作为第⼀个参数(当然可以⽤其他名称的变量作为其第⼀个参数,但是⼤部分⼈都习惯以'cls'作为第⼀个参数的名字,就最好⽤'cls'了),能够通过实例对象和类对象去访问

    •  特性:只能访问类变量,不能访问实例变量
    • 调用方式:通过实例对象或类对象去访问

     

  • 相关阅读:
    🍖名称空间与作用域
    🍖文件打开模式 "t"
    🍖函数参数
    【转】LINQ中的Aggregate语法
    【转】c#中string.trimstart() 和string.trimend() 的用法
    1094 和为k的连续区间(暴力)
    1095 Anigram单词
    1031 骨牌覆盖 (斐波拉契数列)
    最长公共子序列(模板 LCSL)
    1092 回文字符串(LCSL_DP)
  • 原文地址:https://www.cnblogs.com/wang-mengmeng/p/11251949.html
Copyright © 2020-2023  润新知