Python闭包函数和装饰器 闭包函数
概念:在函数中(嵌套)定义另一个函数时,内部函数引用了外层函数的名字。
特性
闭包函数必须在函数内部定义
闭包函数可引用外层函数的名字
闭包函数是函数嵌套、函数对象、名称空间与作用域结合体
闭包中被内部函数引用的变量,不会因为外部函数结束而被释放掉,而是一直存在内存中,直到内部函数被调用结束
# 闭包函数的定义 def func(y): x = 100 def inner(): # 此处的inner 就是闭包函数 print(x) print(y) return inner # 闭包函数的调用 inner = func(1000) inner()应用:为了给装饰器的使用做准备
装饰器概念:在不修改被装饰对象源代码与调用方式的前提下,添加新的功能。简单来说,就是给其他函数增加额外功能的函数
装饰器必须遵循“开放封闭”原则
开放:对函数功能的添加是开放的
封闭:对函数功能的修改是封闭的
必备条件:
不能改变被装饰对象源代码
为被装饰对象添加新的功能
不能改变被装饰对象调用方式
使用装饰器,可以解决代码冗余问题,提高代码的可扩展性
应用:统计时间、登录认证
说了这多理论,上代码。
需求:统计下载媒体文件的时间(简易版)
# 需求: 统计下载电影的时间。 # 一般我们实现这个功能的方式如下 import time def download_movie(): """ 下载电影功能 :return: None """ print("电影下载开始了……") time.sleep(2) # 模拟电影下载2 秒 print("下载完成") start_time = time.time() # 获取当前时间戳 download_movie() # 下载电影 end_time = time.time() # 获取当前时间戳 print(f"下载时间:{end_time-start_time}")以上代码确实实现了统计下载时间的功能,问题来了,如果我有多个类型文件下载函数,都需要统计时间呢?难道展现我们的“CV大法”?估计隔天就要被扫地出门了……
就没有什么办法可以解决了吗?当然有啦!先看代码
# 定义一个装饰器 def time_record(func): """ 新增统计时间功能 :param func: 使用该功能的函数对象 :return: inner 函数对象 """ def inner(): # 统计开始 start_time = time.time() func() # func() ----→ download_movie() or download_music() end_time = time.time() # 统计结束,打印统计时间 print(f"下载时间:{end_time-start_time}") return inner def download_movie(): """ 模拟下载电影 :return: None """ print("电影下载开始了……") time.sleep(2) print("下载完成!") def download_music(): """ 模拟下载音乐 :return: None """ print("歌曲下载开始了……") time.sleep(2) print("下载完成!") # time_record(download_movie) 返回一个inner,将其赋值给download_movie inner = time_record(download_movie) inner() # inner() ----→ download_movie() # time_record(download_music) 返回一个inner,将其赋值给download_music inner1 = time_record2(download_music) inner1()以上代码就是对装饰器的引入,其中 time_record 就是装饰器,download_movie 和 download_music 就是被装饰的函数对象。
通过观察