python装饰器

1.python装饰器


参考 http://c.biancheng.net/view/2270.html

1.1 函数的引用

函数,也可以像变量一样,将一个函数名,赋值给另一个变量名,赋值后,此变量名就可以做为该函数的一个别名使用,进行调用函数。

def show():
    print("Show Run ...")

show()
a = show
a()

**注意:**在将一个函数名(函数引用)赋值给一个变量时,函数名后不能添加括号。带括号是函数执行,不带括号才是函数引用;
应用场景: 函数引用一般在函数的参数或者返回值中使用;

1.2 闭包(closure)

在外部函数中定义了一个内部函数(内部函数是闭包),并且内部函数能够读取到外部函数内的变量,这种函数我们就称为闭包

def out_func(a):
    out_n = 100
    def inner_func():
        # 不能对 out_n进行赋值操作
        print(out_n+a)
    return inner_func #返回内部函数

if __name__ == '__main__':
    of1 = out_func(1)
    of2 = out_func(2)
    #只有这样才可以执行到内部函数部分
    of1()  #101
    of2()  #102

特性:
1)内部函数是闭包
2)内部函数中可以对外部函数的变量/参数引用和修改—— 可以访问外部函数中的变量和参数,以及外部函数所在的作用域中的变量或其他函数对象,它被内部函数引用并记住,即使外部函数执行完成后仍然存在。
3)外部函数返回内部函数名供其他地方使用
nonlocal
在内部函数对外部函数的变量修改,只在内部函数生效,在外部函数部分就无效了(需要使用关键字nonlocal在内部函数里声明下外部函数的变量)

def out_func():
    out_n = 100
    def inner_func():
        nonlocal out_n
        out_n = 200  
        print("inner:",out_n)
    print("outer1:",out_n)
    inner_func()
    print("outer2:",out_n)
    return inner_func


if __name__ == '__main__':
    of1 = out_func()
    of1()
# 结果:
# outer1: 100
# inner: 200
# outer2: 200  无nonlocal声明的话此处打印的是100
# inner: 200

1.3 装饰器

闭包和装饰器的区别:

  • 装饰器是外层的函数(嵌套函数)——外函数参数func是被装饰函数
  • 闭包是内部函数

**装饰器作用:**在不改变函数原有代码的基础上,添加额外的功能

装饰器的应用场景:
引入日志、函数执行时间统计、执行函数前预备处理、执行函数后清理功能、权限校验等场景、缓存、事务处理、数据清理、数据添加、附加功能等

(1)python内置装饰器

https://ceshiren.com/t/topic/28344

  • @staticmethod :被装饰的方法为静态方法,既不属于实例也不属于类,只是类中普通方法(通过类名调用)
  • @classmethod :被装饰的方法为类方法(通过类名调用)
  • @property :将一个函数装饰为一个变量(访问的时候只需.函数名,不需要.函数名())
  • @lru_cache :用来缓存一个函数的结果,这样后续调用相同参数的函数就不会再执行了。它对于计算量大或使用相同参数频繁调用的函数特别有用。
  • 还有其他内置装饰器函数

(2)python自定义装饰器

   def outer(func):
        def inner(y):
            begin = time.time()
            func()
            end = time.time()
        return inner
  
   @outer
   def test(self):  #outer(test),test就是参数func
        pass

装饰器组成:

  • 1、定义一个外部函数outer,并将原函数名func作为参数
  • 2、定义一个内部函数inner,在内部函数中调用func函数,以及添加新增功能;
  • 3、外部函数返回内部函数名inner
  • 4、将外部函数名使用@装饰到原函数,即@outer;

装饰器执行过程:

  • 1、Python解释器在遇到装饰器时,会将被装饰函数引用做为参数传递给闭包的外函数,外函数执行后,返回内函数的引用,此时,再将内函数引用赋值给被装饰器函数。
  • 2、当Python解释器执行完装饰过程后,被装饰函数的函数名就不在保存原函数的引用,而是保存的闭包函数inner的引用。
  • 3、而当执行被装饰函数时,实际执行的是闭包函数inner,由inner间接调用被装饰函数,完成整个调用过程。

2.pytest装饰器


https://blog.csdn.net/qq_45664055/article/details/131992948

2.1pytest内置装饰器

@pytest.fixture 用于定义测试用例的前置条件和后置操作
@pytest.mark.parametrize 用于参数化测试函数(提供不同组的测试数据,形成多个测试案例)
@pytest.mark.skip 跳过不运行的测试案例
@pytest.mark.xfail 预期失败(如果案例失败,则视为测试通过;如果案例并未失败,则视为测试不通过)

2.2pytest自定义装饰器