python基础语法7 闭包函数与装饰器
时间:2019-11-12
本文章向大家介绍python基础语法7 闭包函数与装饰器,主要包括python基础语法7 闭包函数与装饰器使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
闭包函数:
1.闭包函数必须在函数内部定义
2.闭包函数可以引用外层函数的名字
闭包函数是 函数嵌套、函数对象、名称空间与作用域 结合体。
# 直接传参 def func(x): print(x) func(1000) # 通过闭包函数传参 def outer(number): # number = 100 # inner就是闭包函数 def inner(): print(number) return inner func = outer(1000) # ---》 inner地址 ---》 func变量名 func() # func ---> inner地址()
闭包函数的应用
# 方式一: 直接传参 def spider_func(url): # 往url地址发送请求,获取响应数据 response = requests.get(url) # 必须接受url # 状态码: 200 if response.status_code == 200: # 获取当前url地址中所有的文本 print(len(response.text)) print(response.text) url = 'https://www.cnblogs.com/xiaoyuanqujing/' spider_func(url) —————————————————————————— # 方式二: 通过闭包函数接受url地址,执行爬取函数 def spider_outer(url): # url = 'https://www.cnblogs.com/xiaoyuanqujing/' def spider_inner(): response = requests.get(url) if response.status_code == 200: print(len(response.text)) return spider_inner # 爬取 小猿取经 spider_blog = spider_outer('https://www.cnblogs.com/xiaoyuanqujing/') spider_blog() # 爬取 京东 spider_baidu = spider_outer('https://www.baidu.com/') spider_baidu()
装饰器:
不修改被装饰对象的源代码
不修改被装饰对象的调用方式
被装饰对象: ---> 需要添加功能 函数
装饰器: ---> 被装饰对象添加的新功能的 函数
time_record ---》 装饰器
需求: 统计下载电影函数的运行时间。
# 下载电影功能(初始代码) def download_movie(): print('开始下载电影...') # 模拟电影下载时间 3秒 time.sleep(3) # 等待3秒 print('电影下载成功...') return 'sean与jason的雨后的小故事.mp4' start_time = time.time() # 获取当前时间戳 download_movie() end_time = time.time() # 获取当前时间戳 print(f'消耗时间: {end_time - start_time}') # 问题: 多个被装饰对象,需要写多次统计时间的代码,导致代码冗余。
# 装饰器: 初级版 def time_record(func): def inner(*args, **kwargs): # 统计开始 start_time = time.time() # 被装饰对象, 问题1: 有返回值, 问题2: 不确定参数的 个数 res = func(*args, **kwargs) # func() ---> download_movie() # 当被统计的函数执行完毕后,获取当前时间 end_time = time.time() # 统计结束,打印统计时间 print(f'消耗时间: {end_time - start_time}') return res return inner download_movie = time_record(download_movie) # inner # name = 'egon' # download_movie(name) download_movie(name='egon') # inner() # inner() ---> download_movie() # download_movie = time_record(download_movie) # inner
# download_movie() # download_movie() ---> download_movie()
# 问题1: 被装饰对象 有返回值 # 下载电影功能 def download_movie(): print('开始下载电影...') # 模拟电影下载时间 3秒 time.sleep(3) # 等待3秒 print('电影下载成功...') return '小泽.mp4' def time_record(func): # func <-- download_movie # 在闭包函数中 def inner(): # 统计开始 start_time = time.time() res = func() # func() ---> download_movie() # 当被统计的函数执行完毕后,获取当前时间 end_time = time.time() # 统计结束,打印统计时间 print(f'消耗时间: {end_time - start_time}') return res return inner download_movie = time_record(download_movie) download_movie()
#问题2: 被装饰对象 有参数 #下载电影功能 import time def download_movie(url): print(f'{url}中的电影开始下载了...') # 模拟电影下载时间 3秒 time.sleep(3) # 等待3秒 print('电影下载成功...') return '小泽.mp4' def time_record(func): # func <-- download_movie # url = 'https://www.baidu.com/' # 在闭包函数中 def inner(url): # 统计开始 start_time = time.time() res = func(url) # func(url) ---> download_movie(url) # 当被统计的函数执行完毕后,获取当前时间 end_time = time.time() # 统计结束,打印统计时间 print(f'消耗时间: {end_time - start_time}') return res return inner download_movie = time_record(download_movie) download_movie(url) --> inner(url) download_movie('https://www.baidu.com')
#问题4: 假如被装饰对象需要接收多个参数 def download_movie(url, url2, url3): print(f'{url}中的电影开始下载了...') # 模拟电影下载时间 3秒 time.sleep(3) # 等待3秒 print('电影下载成功...') return '小泽.mp4' def download_movie(): print('电影开始下载...') # 模拟电影下载时间 3秒 time.sleep(3) # 等待3秒 print('电影下载成功...') return '小泽.mp4'
# 装饰器最终版本 def time_record(func): # func <-- download_movie # 在闭包函数中 def inner(*args, **kwargs): # *args, **kwargs接收所有参数 # 统计开始 start_time = time.time() # 将被装饰对象需要接收的任意参数 原封不动传给func --》 被装饰对象 res = func(*args, **kwargs) # func(url) ---> download_movie(url) # 当被统计的函数执行完毕后,获取当前时间 end_time = time.time() # 统计结束,打印统计时间 print(f'消耗时间: {end_time - start_time}') return res return inner # download_movie = time_record(download_movie) # # download_movie() # download_movie(url) --> inner(url, url2, url3) # download_movie(url1='https://www.baidu.com', url2='url2', url3='url3')
# 装饰器模板:权限设定 # 装饰器最终版本 def wrapper(func): def inner(*args, **kwargs): # 让用户输入内容 username = input('请输入名字') if username == 'tank': # 调用被装饰对象,得到返回值 res = func(*args, **kwargs) return res else: print('用户权限不足!') return inner def func1(): pass func1 = wrapper(func1) func1() # inner()
装饰器的语法糖,是属于装饰器的。
@: 装饰器的语法糖
# 注意: 在使用装饰器语法糖时,装饰器必须定义在被装饰对象之上。
import time # 统计函数执行时间装饰器 def wrapper(func): # 被装饰对象 def inner(*args, **kwargs): # 被装饰对象的参数 # 调用前增加新功能 start_time = time.time() # 调用被装饰对象,并接收返回值 res = func(*args, **kwargs) # 调用后添加新功能 end_time = time.time() print(end_time - start_time) return res return inner # func函数需要执行3秒 # 无参装饰器 # 使用装饰器 @wrapper # wrapper(func) ---> func def func(): time.sleep(3) func()
原文地址:https://www.cnblogs.com/ludingchao/p/11844921.html
- 如何优化 Android Studio 启动、编译和运行速度?
- 微信小程序左右滑动切换图片酷炫效果(附效果)
- Facebook推出用于android数据加密的开源API
- Android 表单验证框架:AValidations
- 推荐系统介绍
- Android WebView 上传文件支持全解析
- 网站管理软件 – AspxSpy2014 Final
- 特性分支与特性开关哪家强?
- Android快速开发框架 roboguice
- 悄悄的干活,打枪的不要!勒索+比特币挖矿木马
- 拥有可移动头像的折叠Android工具栏:CollapsingAvatarToolbar
- Android平台下的第一个Tor木马
- 利用代码实现自定义圆角+阴影按钮 android-flat-button
- 周末阅读:程序员的《权利法案》
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 简说中台
- JVM进阶
- MapperReduce常见错误及解决方案
- MapReduce案例之寻找共同好友
- JavaScript或ES6如何实现多继承总结【Mixin混合继承模式】
- Hadoop之MapReduce开发总结
- python之文件操作
- 血的教训!千万别在生产使用这些 redis 指令
- Python selenium chrome parses blob url
- 实战|仅用18行JavaScript构建一个倒数计时器
- 译|通过Node和Redis进行API速率限制
- EasySwoole实现Execl导入导出
- 设计模式:参与者风格
- vuepress集成element-ui
- 如何利用unli-app框架快速构建EasyRTC_SFU安卓app项目?