![什么是闭包函数与装饰器,它们有哪些作用? 图片[1]-什么是闭包函数与装饰器,它们有哪些作用?-不念博客](https://www.bunian.cn/wp-content/uploads/2022/12/qqjietu20221230120550.png)
闭包函数
- 闭函数指的是在一个函数内部的函数,即嵌套在函数内部的函数。
- 包函数指的是内部函数对外层函数(非全局作用域)作用域名字的引用。
- 闭包函数基于函数对象,可以将函数返回到任意位置调用,但是作用域的关系在定义函数的时候就被确定了,与函数的调用位置无关。如果内嵌函数包含对外部函数作用域中名字的引用,该内嵌函数就是闭包函数。
# -*- coding: utf-8 -*-def outer():name = 'shisbuyu'def inner():print('外层函数的内层函数inner', name) # 内层函数使用到了外层函数名称空间中名字inner()return innerres = outer() # 得到的返回值是函数名inner# 输出# 外层函数的内层函数inner shisbuyu# -*- coding: utf-8 -*- def outer(): name = 'shisbuyu' def inner(): print('外层函数的内层函数inner', name) # 内层函数使用到了外层函数名称空间中名字 inner() return inner res = outer() # 得到的返回值是函数名inner # 输出 # 外层函数的内层函数inner shisbuyu# -*- coding: utf-8 -*- def outer(): name = 'shisbuyu' def inner(): print('外层函数的内层函数inner', name) # 内层函数使用到了外层函数名称空间中名字 inner() return inner res = outer() # 得到的返回值是函数名inner # 输出 # 外层函数的内层函数inner shisbuyu
闭包函数作用
- 函数体传参方式之 形参
def index(username):print(username)index('shisbuyu') # 函数体代码需要什么就可以在形参里写什么def index(username): print(username) index('shisbuyu') # 函数体代码需要什么就可以在形参里写什么def index(username): print(username) index('shisbuyu') # 函数体代码需要什么就可以在形参里写什么
- 函数体传参方式之 闭包
def outter():name = 'shisbuyu'def index():print(name) # name写死了, 调用res() name shisbuyureturn indexres = outer()res()def outter(): name = 'shisbuyu' def index(): print(name) # name写死了, 调用res() name shisbuyu return index res = outer() res()def outter(): name = 'shisbuyu' def index(): print(name) # name写死了, 调用res() name shisbuyu return index res = outer() res()
做成闭包函数通过形参传参给外层
def outter(name):def index():print(name)return indexres = outter('shisbuyu')res() # shisbuyures1 = outter('shisuiyi')res1() # shisuiyidef outter(name): def index(): print(name) return index res = outter('shisbuyu') res() # shisbuyu res1 = outter('shisuiyi') res1() # shisuiyidef outter(name): def index(): print(name) return index res = outter('shisbuyu') res() # shisbuyu res1 = outter('shisuiyi') res1() # shisuiyi
装饰器
装饰器可以在不改动原函数代码的情况下,添加其原本没有的功能。简单点说,就是 修改其它函数的功能的函数 。通过使用装饰器,我们可以让一个函数的功能变的更加强大,还可以让我们的代码更加简短整洁。
普通装饰器
方式一:不使用语法糖@符号的调用方法:
# -*- coding: utf-8 -*-# 原函数def one():print("这是一个平平无奇的函数")# 定义1个装饰器def loop(func):def wrapper(*args, **kw):for i in range(2):func(*args, **kw)return wrapperloop(one)()# 输出这是一个平平无奇的函数这是一个平平无奇的函数# -*- coding: utf-8 -*- # 原函数 def one(): print("这是一个平平无奇的函数") # 定义1个装饰器 def loop(func): def wrapper(*args, **kw): for i in range(2): func(*args, **kw) return wrapper loop(one)() # 输出 这是一个平平无奇的函数 这是一个平平无奇的函数# -*- coding: utf-8 -*- # 原函数 def one(): print("这是一个平平无奇的函数") # 定义1个装饰器 def loop(func): def wrapper(*args, **kw): for i in range(2): func(*args, **kw) return wrapper loop(one)() # 输出 这是一个平平无奇的函数 这是一个平平无奇的函数
方式二:使用语法糖@符号的调用方法:
# -*- coding: utf-8 -*-# 定义1个装饰器def loop(func):def wrapper(*args, **kw):for i in range(2):func(*args, **kw)return wrapper@loopdef one():print("这是一个平平无奇的函数")one()# 输出这是一个平平无奇的函数这是一个平平无奇的函数# -*- coding: utf-8 -*- # 定义1个装饰器 def loop(func): def wrapper(*args, **kw): for i in range(2): func(*args, **kw) return wrapper @loop def one(): print("这是一个平平无奇的函数") one() # 输出 这是一个平平无奇的函数 这是一个平平无奇的函数# -*- coding: utf-8 -*- # 定义1个装饰器 def loop(func): def wrapper(*args, **kw): for i in range(2): func(*args, **kw) return wrapper @loop def one(): print("这是一个平平无奇的函数") one() # 输出 这是一个平平无奇的函数 这是一个平平无奇的函数
函数带参数
# -*- coding: utf-8 -*-def loop(func):def wrapper(*args, **kw):for i in range(2):func(*args, **kw)return wrapper@loopdef one(num):for i in range(num):print("这是一个平平无奇的函数")one(2)#输出这是一个平平无奇的函数这是一个平平无奇的函数这是一个平平无奇的函数这是一个平平无奇的函数# -*- coding: utf-8 -*- def loop(func): def wrapper(*args, **kw): for i in range(2): func(*args, **kw) return wrapper @loop def one(num): for i in range(num): print("这是一个平平无奇的函数") one(2) #输出 这是一个平平无奇的函数 这是一个平平无奇的函数 这是一个平平无奇的函数 这是一个平平无奇的函数# -*- coding: utf-8 -*- def loop(func): def wrapper(*args, **kw): for i in range(2): func(*args, **kw) return wrapper @loop def one(num): for i in range(num): print("这是一个平平无奇的函数") one(2) #输出 这是一个平平无奇的函数 这是一个平平无奇的函数 这是一个平平无奇的函数 这是一个平平无奇的函数
带返回值
# -*- coding: utf-8 -*-def loop(func):def wrapper(*args, **kw):ret = func(*args, **kw)return retreturn wrapper@loopdef one(a, b):return a + bres = one(1, 2)print(res)# 当使用@loop对one()函数装饰以后,one指向了wrapper()函数,而wrapper()函数的返回值是ret,所以one()函数的返回值被ret接收了#输出3# -*- coding: utf-8 -*- def loop(func): def wrapper(*args, **kw): ret = func(*args, **kw) return ret return wrapper @loop def one(a, b): return a + b res = one(1, 2) print(res) # 当使用@loop对one()函数装饰以后,one指向了wrapper()函数,而wrapper()函数的返回值是ret,所以one()函数的返回值被ret接收了 #输出 3# -*- coding: utf-8 -*- def loop(func): def wrapper(*args, **kw): ret = func(*args, **kw) return ret return wrapper @loop def one(a, b): return a + b res = one(1, 2) print(res) # 当使用@loop对one()函数装饰以后,one指向了wrapper()函数,而wrapper()函数的返回值是ret,所以one()函数的返回值被ret接收了 #输出 3
实际案例
日志装饰器
# -*- coding: utf-8 -*-import loggingimport os'''* %(asctime)s 即日志记录时间,精确到毫秒@breif:* %(levelname)s 即此条日志级别@param[in]:* %(filename)s 即触发日志记录的python文件名@retval:* %(funcName)s 即触发日志记录的函数名* %(lineno)s 即触发日志记录代码的行号* %(message)s 即这项调用中的参数'''if not os.path.exists('Log.log'):file = open('Log.log', 'w')logging.basicConfig(filename='Log.log',format="%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s")'''* @breif: 日志修饰器,为函数添加日志记录服务* @param[in]: err -> 发生异常时返回的错误信息* @retval: 加载日志服务的功能函数'''def logger(err):def log(func):def warp(*args, **kwargs):try:result = func(*args, **kwargs)return resultexcept Exception as e:logging.error(e)return errreturn warpreturn log@logger('出错了')def add(a, b):return a + bprint(add(1, 2))#控制台输出出错了# Log.log日志显示2022-12-13 14:11:22,772 - ERROR - 闭包函数.py - warp - 36 - unsupported operand type(s) for +: 'int' and 'str'# -*- coding: utf-8 -*- import logging import os ''' * %(asctime)s 即日志记录时间,精确到毫秒@breif: * %(levelname)s 即此条日志级别@param[in]: * %(filename)s 即触发日志记录的python文件名@retval: * %(funcName)s 即触发日志记录的函数名 * %(lineno)s 即触发日志记录代码的行号 * %(message)s 即这项调用中的参数 ''' if not os.path.exists('Log.log'): file = open('Log.log', 'w') logging.basicConfig( filename='Log.log', format="%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s" ) ''' * @breif: 日志修饰器,为函数添加日志记录服务 * @param[in]: err -> 发生异常时返回的错误信息 * @retval: 加载日志服务的功能函数 ''' def logger(err): def log(func): def warp(*args, **kwargs): try: result = func(*args, **kwargs) return result except Exception as e: logging.error(e) return err return warp return log @logger('出错了') def add(a, b): return a + b print(add(1, 2)) #控制台输出 出错了 # Log.log日志显示 2022-12-13 14:11:22,772 - ERROR - 闭包函数.py - warp - 36 - unsupported operand type(s) for +: 'int' and 'str'# -*- coding: utf-8 -*- import logging import os ''' * %(asctime)s 即日志记录时间,精确到毫秒@breif: * %(levelname)s 即此条日志级别@param[in]: * %(filename)s 即触发日志记录的python文件名@retval: * %(funcName)s 即触发日志记录的函数名 * %(lineno)s 即触发日志记录代码的行号 * %(message)s 即这项调用中的参数 ''' if not os.path.exists('Log.log'): file = open('Log.log', 'w') logging.basicConfig( filename='Log.log', format="%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s" ) ''' * @breif: 日志修饰器,为函数添加日志记录服务 * @param[in]: err -> 发生异常时返回的错误信息 * @retval: 加载日志服务的功能函数 ''' def logger(err): def log(func): def warp(*args, **kwargs): try: result = func(*args, **kwargs) return result except Exception as e: logging.error(e) return err return warp return log @logger('出错了') def add(a, b): return a + b print(add(1, 2)) #控制台输出 出错了 # Log.log日志显示 2022-12-13 14:11:22,772 - ERROR - 闭包函数.py - warp - 36 - unsupported operand type(s) for +: 'int' and 'str'
自动化测试脚本中处理异常
举个例子,你正在跑一个自动化测试脚本,突然间设备的闹钟响了,而刚好闹钟的界面遮挡住了你要操作的那个按钮,最终导致脚本运行失败了。没办法,你只能关掉闹钟再重新运行一次脚本。
# -*- coding: utf-8 -*-def test_retry(func):def run_case_again(*args, **kwargs):try:func(*args, **kwargs)except:# 如闹铃、断网重试按钮弹出、短信通知等导致失败if exists(xxxx):touch(xxx)try:func(*args, **kwargs)print('用例重新执行成功')except:print('用例执行失败')# 其他你想做的操作,比如停止剩余用例的执行return run_case_again@test_retrydef test():wait(xxxx, timeout=15)# -*- coding: utf-8 -*- def test_retry(func): def run_case_again(*args, **kwargs): try: func(*args, **kwargs) except: # 如闹铃、断网重试按钮弹出、短信通知等导致失败 if exists(xxxx): touch(xxx) try: func(*args, **kwargs) print('用例重新执行成功') except: print('用例执行失败') # 其他你想做的操作,比如停止剩余用例的执行 return run_case_again @test_retry def test(): wait(xxxx, timeout=15)# -*- coding: utf-8 -*- def test_retry(func): def run_case_again(*args, **kwargs): try: func(*args, **kwargs) except: # 如闹铃、断网重试按钮弹出、短信通知等导致失败 if exists(xxxx): touch(xxx) try: func(*args, **kwargs) print('用例重新执行成功') except: print('用例执行失败') # 其他你想做的操作,比如停止剩余用例的执行 return run_case_again @test_retry def test(): wait(xxxx, timeout=15)
© 版权声明
本站文章由不念博客原创,未经允许严禁转载!
THE END