闭包函数:
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()
定义
装饰的工具
必须要遵循的原则:“开放封闭”
开放:对源函数功能的添加是开放的
封闭:对源函数功能修改是封闭的
装饰器的作用
# 装饰器推导过程 def move(): '''下载电影的源函数''' print('开始下载') time.sleep(2) print('下载完成') def fun(index): def down(): star_time = time.time() index() # 将被装饰对象move赋值给index执行 end_time = time.time() print(f'总耗时{end_time - star_time}') return down fun(move)()
# 有返回值时 def move(): '''下载电影的源函数''' print('开始下载') time.sleep(2) print('下载完成') return '明日之巅.mp4' def fun(index): def down(): star_time = time.time() res = index() # 将index执行结果赋值给res # print(res) end_time = time.time() print(f'总耗时{end_time - star_time}') return res # 将index返回值返回出来 # print(down()) return down move = fun(move) # 将调用方式改成被装饰对象 move()
# 源函数有参数时 def move(url): '''下载电影的源函数''' print(f'{url}开始下载') time.sleep(2) print('下载完成') return '明日之巅.mp4' def wrapper(func): def inner(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print(f'总耗时:{end_time - start_time}') return res return inner move = wrapper(move) move(('https://www.cnblogs.com'))
def wrapper(func): def inner(*args, **kwargs): # 调用前增加新功能 res = func(*args, **kwargs) # 调用被装饰对象,接收返回值 # 调用后增加的新功能 return res # 接收被装饰对象的返回值 return inner
装饰器语法糖
2、用@+装饰器名,在被装饰对象开头
3、在使用装饰器语法糖时,装饰器必须定义在被装饰对象之上
在不修改被装饰对象源代码和调用方式的前提下,增加新功能
必须遵循的原则:
1、不修改被装饰对象的源代码
2、不修改被装饰对象的调用方式
为什么要使用装饰器
解决代码冗余问题,提高代码可扩展性
怎么使用装饰器
编写装饰器通过闭包函数实现
装饰器推导过程
# 增加统计代码运行时间的装饰器 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 # 使用语法糖 @wrapper def movie(): print("开始下载") time.sleep(2) print('下载结束') # 不使用语法糖调用增加新功能后的函数 # movie = wrapper(movie) # movie() # 使用语法糖后可直接调用 movie()