闭包与装饰器

一、闭包:

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、最内层:接收的是被装饰函数或者类的参数


posted @ 2021-10-20 13:03  %女王%  阅读(53)  评论(0编辑  收藏  举报