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 预期失败(如果案例失败,则视为测试通过;如果案例并未失败,则视为测试不通过)