一、闭包:
1、外层函数内定义内置函数
2、外层函数返回值为内层函数的函数名
3、内层函数引用外层函数的非全局变量
def fun(a):
def wrapper():
pass # 对外层函数非全局变量的引用
return wrapper
二、装饰器
1)装饰器的作用:在不更改原功能函数内部代码,并且不改变调用方法的情况下为原函数添加新的功能
2)python的开放封闭原则:软件实体应该是可扩展的,而不可修改的。也就是说,对于扩展是开放的,而对修改是封闭的。
3)装饰器的应用场景:
a.登录验证
b.函数运行时间统计
c.执行函数之前做准备工作
d.执行函数后清理工作
4)装饰器的实现
a.闭包实现装饰器(常用)
b.普通函数也能作为装饰器(不常用)
c.类实现装饰器(常用)
注:如果要通过装饰器去装饰类或者有返回值的函数时,一定在装饰器内部将类或者函数调用的结果返回。
5)装饰器的原理
@ddt ====》此处实现的就是 test = ddt(test)
def test():
pass
1、普通装饰器
定义:
def decorator(func):
def wrapper(*args,**kwargs):
# 此处为加上扩展功能
res = func(*args,**kwargs) #变量接收被装饰类或者有返回值的函数的返回值
# 此处为加上扩展功能
return res # 如果被装饰的是类或者返回值的函数,那么内层函数一定要将这个返回值返回
return wrapper
2、装饰器装饰类
1)闭包实现的装饰器
def decorator(func):
def wrapper(*args,**kwargs):
print("------装饰器执行了--1---")
obj = func(*args,**kwargs) #======>此处是创建了一个对象,需要返回
print("-----装饰器执行了---2---")
return obj
return wrapper
@decorator #=======》MyTest = decorator(MyTest)
class MyTest:
def test_login(self):
print("-----MyTest----test_login")
m = MyTest()
print(m)
2)普通函数实现的装饰器(非闭包实现的装饰器去装饰类)
动态的给类添加属性
实现简单版的ddt
ddt装饰器
#myddt.py
def ddt(cls):
for name, value in list(cls.__dict__.items()):
if hasattr(value, "DATA"):
data = getattr(value, "DATA")
for i in data:
setattr(cls, "test_{}".format(i), value)
return cls
def data(test_data):
def my_data(func):
setattr(func, "DATA", test_data)
return func
return my_data
#MyTest.py
@ddt
class MyTest(unittest.TestCase):
@data([1, 2, 3, 4, 5])
def test_login(self):
print("这里是登录用例的测试")
#run.py
suite = unittest.defaultTestLoader.loadTestsFromTestCase(MyTest)
runner = unittestreport.TestRunner(suite)
runner.run()
3、带参数的的装饰器(三层)
定义:
def decorator(number1,number2...):
def decorator_wrapper(func):
def wrapper(*args,**kwargs):
print("此处可以是对number各参数的引用")
res = func(*args,**kwargs)
print("此处可以是对number各参数的处理")
return res
return wrapper
return decorator_wrapper
三层装饰器:
1、最外层:接收的是装饰器的参数
2、第二层:接收的是被装饰的函数或者类
3、最内层:接收的是被装饰函数或者类的参数