python---闭包
1.闭包理解
闭包定义:在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包
2.必报的构成条件:
在函数嵌套(函数里面在定义函数)的前提下
内部函数使用了外部函数的变量(还包括外部函数的参数)
外部函数返回了内部函数
3.闭包书写步骤:
定义外部函数
定义外部函数,在内部函数中使用外部函数的变量
外部函数返回内部函数的地址
代码需求:一个初始值 num对 num 的基础上进行 加法运算
# 定义内部函数:def outer(num): # 2.定义内部函数,在内部函数中使用外部函数的变量 def inner(num1): print(num + num1) # 3.外部函数返回内部函数的地址 return inner # 函数名字就是函数地址if __name__ == '__main__': # 创建闭包实例 func = outer(100) # 此时func相当于是inner # 调用闭包 func(10) # 此时调用inner函数,保存的num值为100# 可以创建多个闭包实例,不同的闭包实例之间,不会相互影响
2.闭包的使用
案例:根据配置信息使用闭包实现不同人的对话信息,例如对话:
张三:到北京了吗?
李四:已经到了,放心吧。
实现步骤说明
定义外部函数接受不同的配置信息参数,参数是人名
定义内部函数接受对话信息参数
在内部函数里面把配置信息和对话信息进行拼接输出
def outer(name): # 定义内部函数,参数是 说话的信息 print(f'{name}:到北京了吗?') def inner(name1): # 内部函数中,将name和info进行拼接输出 print(f'{name1}:已经到了,放心吧。') # 外部函数返回内部函数的地址 return inner# 创建闭包实例if __name__ == '__main__': func = outer('张三') func('李四')
注意点:由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。
3.闭包修改外部函数变量(理解)
函数内部想要修改全局变量,使用global关键字
在闭包函数内部,想要修改外部函数的局部变量,需要使用nonlocal关键字
def outer(): num = 10 def inner(): # num = 100 # 不是修改外部变量的值,重新定义的局部变量 nonlocal num # 声明使用外部变量 num 不重新定义 num = 100 print(f'调用inner之前:{num}') inner() print(f'调用inner之后:{num}') return innerfunc = outer()func()
4.装饰器(理解)
装饰器的功能:就是给已有函数添加新的功能 1.不修改已有函数的1源代码 2.不修改已有函数的调用方式 3.给函数添加功能 装饰器本质就是一个闭包函数,只不过比较特殊1.定义外层函数(要求参数只有一个,类型是函数类型,调用时传参传递的是原函数)2.定义内层函数,在内层函数中,书写新的功能,并在合适的时机调用原函数3.返回内部函数的地址 装饰器的书写方法: 新的功能和原函数进行对比,查看需要的新的功能,将新功能书写在inner的内层函数中案例需求:原函数: comment() 一个评论功能新的需求:在评论之前,检查是否登录
# -------------------装饰器-----------------def login_check(fn): def inner(): # 书写新的功能,使用print进行模拟 print('登录验证......') # 新的功能书写完成之后,调用原函数 fn() return inner# 装饰器的语法糖格式,@login_check # comment =login_check(comment)def comment(): # 使用print输出模拟评论功能 print('进行评论检查......')# 在调用之前创建闭包实例# func = login_check(comment)comment = login_check(comment)if __name__ == '__main__': comment()
5.装饰器语法糖格式替换时机
def func(): pass func()需求:统计函数执行所消耗的时间(新)1.执行函数前记录当前时间2.执行函数3.函数执行结束之后,再次记录当前时间(新)两次的时间差就是就是函数执行的时间
-----装饰器语法糖格式替换时机-----import time# 定义装饰器函数:def calc_time(fn): def inner(): # 记录当前时间 start = time.time() # 记录当前时间的秒数 fn() end = time.time() print(f'函数耗时{end - start}') return inner# 定义原函数@calc_timedef func(): for i in range(10): print(i) time.sleep(0.3) print('函数执行')if __name__ == '__main__': func()
6.装饰器输出日志信息
需求: def func1(): pass def func2(): pass在每次进入函数时:输出 func1 enter......函数执行结束之后,输出 func leave.....分析步骤:1.函数执行前,输出func1 enter....2.执行函数3.执行结束, 输出 func1 leave.....
# 定义原函数:def logger(fn): def inner(*args, **kwargs): print(f'{fn.__name__} enter....') fn(*args, **kwargs) print(f'{fn.__name__} leave....') return inner@loggerdef comment1(): print('评论功能:')@loggerdef func(num): print(num)if __name__ == '__main__': comment1() func(10)
11.装饰带返回值的函数
不管原函数有没有返回值,装饰器的内部函数都应该将fn函数的返回值进行返回
如果原函数有返回值,返回的就是原函数的返回值
如果没有返回的是None
# func(10)# ----装饰带返回值的函数---def logger(fn): def inner(*args, **kwargs): print(f'{fn.__name__} enter....') result=fn(*args, **kwargs) print(f'{fn.__name__} leave....') # 函数没有书写返回值,默认返回None return result return inner@loggerdef func(into): return into@loggerdef my_sum(a, b): return a + bif __name__ == '__main__': print(func('hello')) print(func((3, 6)))
12.通用装饰器
def decorate(fn): def inner(*args,**kwargs): ... result=fn(*args,**kwargs) return result return inner
13.多个装饰器装饰同一个函数
def comment(info): return info 1.书写一个装饰器 给原函数的返回值加上p 标签返回值
2.书写一个装饰器,给 原函数加上 div标签 返回值
# ---多个装饰器装饰同一个函数----def make_p(fn): def inner(info): result = fn(info) return '' + result + '
' return inner### @make_p# def comment(info):# return info### if __name__ == '__main__':# print(comment('hello world'))def make_div(fn): def inner(info): result = fn(info) return '' + result + '' return inner# 多个装饰器装饰同一个函数,装饰顺序是就近原则,谁离原函数近,就先装饰谁# 1.comment =make_p(comment)# 2.comment =make_div(comment)@make_div@make_pdef comment(info): return infoif __name__ == '__main__': print(comment('hello world!'))
14.带参数的装饰器
# 装饰器 make_tag@make_tag('div')@make_tag('p')def comment(): pass1.当代码执行到第4行,@make_tag('div') def make_tag(tag): 返回一个装饰器
def make_tag(tag): # 返回一个装饰器 def decorate(fn): def inner(*args, **kwargs): result = fn(*args, **kwargs) return f'<> {tag}>{result}{tag}' return inner return decorate # 返回装饰器# 1.先进行函数调用,返回装饰器# 2.对原函数进行装饰@make_tag('aini')@make_tag('div')@make_tag('p')def comment(info): return infoif __name__ == '__main__': print(comment('hello world'))
15.题目训练加强
1.闭包的特点是什么?
1.外部函数中定义了一个内部函数
2.外部函数总是返回内部函数的引用
3.内部函数可以使用外部函数提供的环境变量
2.创建一个闭包,实现统计函数执行的次数功能
有如下调用闭包函数的代码
f=func_count()f()f()f()
def func_count(): num = 0 def inner(): nonlocal num num += 1 print('hello world') print(f'共执行次数{num}') return innerif __name__ == '__main__': f = func_count() # 调用闭包 f() f() f()
3.实现装饰器,实现对函数执行时间进行计算的能力
import timedef outer(fn): def inner(): start = time.time() fn() end = time.time() print(f'{end - start}') return inner@outerdef func(): for i in range(10): print(i) time.sleep(0.3)if __name__ == '__main__': func()
4.一个函数,返回一个字符串,使用装饰器实现对这个字符串添加后缀.txt
def func(fn): def inner(info): result = fn(info) return result + '.txt' return inner@funcdef comment(into): return intoif __name__ == '__main__': print(comment('hello world'))
来源地址:https://blog.csdn.net/zzh_love/article/details/129007703
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341