当前位置:   article > 正文

python---闭包_python 闭包

python 闭包

1.闭包理解

  1. 闭包定义:在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包

2.必报的构成条件:

  • 在函数嵌套(函数里面在定义函数)的前提下

  • 内部函数使用了外部函数的变量(还包括外部函数的参数)

  • 外部函数返回了内部函数

3.闭包书写步骤:

  • 定义外部函数

  • 定义外部函数,在内部函数中使用外部函数的变量

  • 外部函数返回内部函数的地址

  1. 代码需求:
  2. 一个初始值 num
  3. 对 num 的基础上进行 加法运算
  1. # 定义内部函数:
  2. def outer(num):
  3. # 2.定义内部函数,在内部函数中使用外部函数的变量
  4. def inner(num1):
  5. print(num + num1)
  6. # 3.外部函数返回内部函数的地址
  7. return inner # 函数名字就是函数地址
  8. if __name__ == '__main__':
  9. # 创建闭包实例
  10. func = outer(100) # 此时func相当于是inner
  11. # 调用闭包
  12. func(10) # 此时调用inner函数,保存的num值为100
  13. # 可以创建多个闭包实例,不同的闭包实例之间,不会相互影响

2.闭包的使用

  1. 案例:根据配置信息使用闭包实现不同人的对话信息,例如对话:

张三:到北京了吗?

李四:已经到了,放心吧。

  1. 实现步骤说明

  • 定义外部函数接受不同的配置信息参数,参数是人名

  • 定义内部函数接受对话信息参数

  • 在内部函数里面把配置信息和对话信息进行拼接输出

  1. def outer(name):
  2. # 定义内部函数,参数是 说话的信息
  3. print(f'{name}:到北京了吗?')
  4. def inner(name1):
  5. # 内部函数中,将name和info进行拼接输出
  6. print(f'{name1}:已经到了,放心吧。')
  7. # 外部函数返回内部函数的地址
  8. return inner
  9. # 创建闭包实例
  10. if __name__ == '__main__':
  11. func = outer('张三')
  12. func('李四')

注意点:由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存。

3.闭包修改外部函数变量(理解)

函数内部想要修改全局变量,使用global关键字
在闭包函数内部,想要修改外部函数的局部变量,需要使用nonlocal关键字
  1. def outer():
  2. num = 10
  3. def inner():
  4. # num = 100 # 不是修改外部变量的值,重新定义的局部变量
  5. nonlocal num # 声明使用外部变量 num 不重新定义
  6. num = 100
  7. print(f'调用inner之前:{num}')
  8. inner()
  9. print(f'调用inner之后:{num}')
  10. return inner
  11. func = outer()
  12. func()

4.装饰器(理解)

  1. 装饰器的功能:就是给已有函数添加新的功能
  2. 1.不修改已有函数的1源代码
  3. 2.不修改已有函数的调用方式
  4. 3.给函数添加功能
  5. 装饰器本质就是一个闭包函数,只不过比较特殊
  6. 1.定义外层函数(要求参数只有一个,类型是函数类型,调用时传参传递的是原函数)
  7. 2.定义内层函数,在内层函数中,书写新的功能,并在合适的时机调用原函数
  8. 3.返回内部函数的地址
  9. 装饰器的书写方法: 新的功能和原函数进行对比,查看需要的新的功能,将新功能书写在inner的内层函数中
  10. 案例需求:
  11. 原函数: comment() 一个评论功能
  12. 新的需求:在评论之前,检查是否登录
  1. # -------------------装饰器-----------------
  2. def login_check(fn):
  3. def inner():
  4. # 书写新的功能,使用print进行模拟
  5. print('登录验证......')
  6. # 新的功能书写完成之后,调用原函数
  7. fn()
  8. return inner
  9. # 装饰器的语法糖格式,
  10. @login_check # comment =login_check(comment)
  11. def comment():
  12. # 使用print输出模拟评论功能
  13. print('进行评论检查......')
  14. # 在调用之前创建闭包实例
  15. # func = login_check(comment)
  16. comment = login_check(comment)
  17. if __name__ == '__main__':
  18. comment()

5.装饰器语法糖格式替换时机

  1. def func():
  2. pass
  3. func()
  4. 需求:统计函数执行所消耗的时间(新)
  5. 1.执行函数前记录当前时间
  6. 2.执行函数
  7. 3.函数执行结束之后,再次记录当前时间(新)
  8. 两次的时间差就是就是函数执行的时间
  1. -----装饰器语法糖格式替换时机-----
  2. import time
  3. # 定义装饰器函数:
  4. def calc_time(fn):
  5. def inner():
  6. # 记录当前时间
  7. start = time.time() # 记录当前时间的秒数
  8. fn()
  9. end = time.time()
  10. print(f'函数耗时{end - start}')
  11. return inner
  12. # 定义原函数
  13. @calc_time
  14. def func():
  15. for i in range(10):
  16. print(i)
  17. time.sleep(0.3)
  18. print('函数执行')
  19. if __name__ == '__main__':
  20. func()

6.装饰器输出日志信息

  1. 需求:
  2. def func1():
  3. pass
  4. def func2():
  5. pass
  6. 在每次进入函数时:输出 func1 enter......
  7. 函数执行结束之后,输出 func leave.....
  8. 分析步骤:
  9. 1.函数执行前,输出func1 enter....
  10. 2.执行函数
  11. 3.执行结束, 输出 func1 leave.....
  1. # 定义原函数:
  2. def logger(fn):
  3. def inner(*args, **kwargs):
  4. print(f'{fn.__name__} enter....')
  5. fn(*args, **kwargs)
  6. print(f'{fn.__name__} leave....')
  7. return inner
  8. @logger
  9. def comment1():
  10. print('评论功能:')
  11. @logger
  12. def func(num):
  13. print(num)
  14. if __name__ == '__main__':
  15. comment1()
  16. func(10)

11.装饰带返回值的函数

不管原函数有没有返回值,装饰器的内部函数都应该将fn函数的返回值进行返回

  1. 如果原函数有返回值,返回的就是原函数的返回值

  1. 如果没有返回的是None

  1. # func(10)
  2. # ----装饰带返回值的函数---
  3. def logger(fn):
  4. def inner(*args, **kwargs):
  5. print(f'{fn.__name__} enter....')
  6. result=fn(*args, **kwargs)
  7. print(f'{fn.__name__} leave....')
  8. # 函数没有书写返回值,默认返回None
  9. return result
  10. return inner
  11. @logger
  12. def func(into):
  13. return into
  14. @logger
  15. def my_sum(a, b):
  16. return a + b
  17. if __name__ == '__main__':
  18. print(func('hello'))
  19. print(func((3, 6)))

12.通用装饰器

  1. def decorate(fn):
  2. def inner(*args,**kwargs):
  3. ...
  4. result=fn(*args,**kwargs)
  5. return result
  6. return inner

13.多个装饰器装饰同一个函数

  1. def comment(info):
  2. return info
  3. 1.书写一个装饰器 给原函数的返回值加上p 标签
  4. <p>返回值</p>
  5. 2.书写一个装饰器,给 原函数加上 div标签
  6. <div> 返回值 </div>
  1. # ---多个装饰器装饰同一个函数----
  2. def make_p(fn):
  3. def inner(info):
  4. result = fn(info)
  5. return '<p>' + result + '</p>'
  6. return inner
  7. #
  8. #
  9. # @make_p
  10. # def comment(info):
  11. # return info
  12. #
  13. #
  14. # if __name__ == '__main__':
  15. # print(comment('hello world'))
  16. def make_div(fn):
  17. def inner(info):
  18. result = fn(info)
  19. return '<div>' + result + '</div>'
  20. return inner
  21. # 多个装饰器装饰同一个函数,装饰顺序是就近原则,谁离原函数近,就先装饰谁
  22. # 1.comment =make_p(comment)
  23. # 2.comment =make_div(comment)
  24. @make_div
  25. @make_p
  26. def comment(info):
  27. return info
  28. if __name__ == '__main__':
  29. print(comment('hello world!'))

14.带参数的装饰器

  1. # 装饰器 make_tag
  2. @make_tag('div')
  3. @make_tag('p')
  4. def comment():
  5. pass
  6. 1.当代码执行到第4行,@make_tag('div')
  7. def make_tag(tag):
  8. 返回一个装饰器
  1. def make_tag(tag):
  2. # 返回一个装饰器
  3. def decorate(fn):
  4. def inner(*args, **kwargs):
  5. result = fn(*args, **kwargs)
  6. return f'<> {tag}>{result}</{tag}'
  7. return inner
  8. return decorate # 返回装饰器
  9. # 1.先进行函数调用,返回装饰器
  10. # 2.对原函数进行装饰
  11. @make_tag('aini')
  12. @make_tag('div')
  13. @make_tag('p')
  14. def comment(info):
  15. return info
  16. if __name__ == '__main__':
  17. print(comment('hello world'))

15.题目训练加强

1.闭包的特点是什么?

1.外部函数中定义了一个内部函数
2.外部函数总是返回内部函数的引用
3.内部函数可以使用外部函数提供的环境变量

2.创建一个闭包,实现统计函数执行的次数功能

有如下调用闭包函数的代码

  1. f=func_count()
  2. f()
  3. f()
  4. f()
  1. def func_count():
  2. num = 0
  3. def inner():
  4. nonlocal num
  5. num += 1
  6. print('hello world')
  7. print(f'共执行次数{num}')
  8. return inner
  9. if __name__ == '__main__':
  10. f = func_count()
  11. # 调用闭包
  12. f()
  13. f()
  14. f()

3.实现装饰器,实现对函数执行时间进行计算的能力

  1. import time
  2. def outer(fn):
  3. def inner():
  4. start = time.time()
  5. fn()
  6. end = time.time()
  7. print(f'{end - start}')
  8. return inner
  9. @outer
  10. def func():
  11. for i in range(10):
  12. print(i)
  13. time.sleep(0.3)
  14. if __name__ == '__main__':
  15. func()

4.一个函数,返回一个字符串,使用装饰器实现对这个字符串添加后缀.txt

  1. def func(fn):
  2. def inner(info):
  3. result = fn(info)
  4. return result + '.txt'
  5. return inner
  6. @func
  7. def comment(into):
  8. return into
  9. if __name__ == '__main__':
  10. print(comment('hello world'))

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/855858
推荐阅读
相关标签
  

闽ICP备14008679号