目录
一、 闭包的介绍
1. 闭包的定义
2. 闭包的构成条件
3. 闭包的格式
4. 闭包的作用
二、闭包的使用
1.案例
2.实现步骤说明
3.功能实现代码
三、修改闭包内使用的外部变量
四、装饰器
1.装饰器的定义
2.装饰器的功能特点:
3.装饰器的语法格式
4.装饰器的语法糖写法
五、装饰器的使用
1.装饰器的使用场景
2.装饰器实现已有函数执行时间的统计
3.通用装饰器的使用
4.多个装饰器的使用
5.带有参数的装饰器
一、 闭包的介绍
1. 闭包的定义
闭:封闭。相当于嵌套函数
包:对数据进行操作的函数(就是内层函数)
闭包函数:在一个嵌套函数内外层函数要返回内层函数,并且这个被返回的内层函数还要使用(操作)外层函数的数据(变量 , 参数),这就是闭包
2. 闭包的构成条件
1、必须是一个嵌套函数
2、内层函数必须操作外层函数数据
3、外层函数必须返回内层函数
3. 闭包的格式
格式:
def 函数名():
def 内层函数名():
函数体 # 内层函数必须操作外层函数数据
return 内层函数名
示例:
# 1.函数嵌套
def func_out():
# 外部函数
num1 = 500
def func_inner():
# 内部函数
# 2.内部函数必须使用外部函数的变量
num2 = num1 +500
return num2
# 3.外部函数要返回内部函数
return func_out
# 获取闭包对象
# 这个new_func就是闭包
new_func = func_out() # new_func = func_inner
# 执行闭包
new_func()
闭包函数的本质:间接修改数据,保护外层函数的数据不被破坏
4. 闭包的作用
闭包可以保存外部函数内的变量,不会随着外部函数调用完而销毁。
注意:由于闭包引用了外部函数的变量,则外部函数的变量没有及时释放,消耗内存
二、闭包的使用
1.案例
需求:根据配置信息使用闭包实现不同人的对话,例如对话:
老师:今天作业交了没有?
学生:放心吧,都交了!
2.实现步骤说明
1.定义外部函数接收不同的配置信息参数,参数是人名
2.定义内部函数接收对话信息参数
3.在内部函数里面把配置信息和对话内容进行拼接输出
3.功能实现代码
def config_name(name):
def inner(msg):
print(name + ":" + msg)
return inner
teacher = config_name('老师')
student = config_name('学生')
teacher("今天作业交了没有")
student("放心吧,都交了!")
三、修改闭包内使用的外部变量
修改闭包内使用的外部变量我们需要使用到nonlocal关键字。
示例:
def func_out():
num1 = 100
def func_inner():
nonlocal num1
num1 = 500
result = num1 +100
print(result)
return func_inner
new_func = func_out()
new_func()
四、装饰器
1.装饰器的定义
就是给已有函数增加额外的功能函数,装饰器的本质是一个函数 , 是一个特殊的闭包 。
2.装饰器的功能特点:
1.不修改已有函数的源代码
2.不修改已有函数的调用方式
3.给已有函数增加额外的功能
3.装饰器的语法格式
格式:
def decorator(func):
def inner():
...执行函数之前...
func() # 执行被装饰的目标函数
...执行函数之后...
return inner
示例:
# 定义装饰器
def decorator(func): # 如果闭包函数的参数有且只有一个并且是函数类型,那么这个闭包函数就称为装饰器
def inner():
# 在内部函数里面对已有函数进行装饰
print("已添加登录认证")
func()
return inner
def comment():
print("发表评论")
# 调用装饰器对已有函数进行装饰
comment = decorator(comment)
# 调用方式不变
comment()
代码说明:
闭包函数有且只有一个参数,必须是函数类型,这样定义的函数才是装饰器。
写代码要遵循开放封闭原则,它规定已经实现的功能代码不允许修改,但可以被扩展
执行结果:
已添加登录认证
发表评论
4.装饰器的语法糖写法
如果有多个函数都需要添加登录验证的功能,每次都需要编写func = check(func)这样代码对已有函数进行装饰,这种写法还是比较麻烦。
Python提供了一个装饰器函数更加简单的写法,那就是语法糖,语法糖的书写格式是:@装饰器名,通过语法糖的方式可以完成对已有函数的装饰
# 定义装饰器
def decorator(func):
def inner():
print("已添加登录认证")
func()
return inner
@decorator # 等于comment = decorator(comment)
def comment():
print("发表评论")
comment()
装饰器的执行时机:当当前模块加载完成以后,装饰器会立即执行,对已有的函数进行封装
执行结果:
已添加登录认证
发表评论
五、装饰器的使用
1.装饰器的使用场景
1.函数执行时间的统计
2.输出日志信息
2.装饰器实现已有函数执行时间的统计
import time
def decorator(func):
def inner():
begin = time.time()
func()
end = time.time()
result = end - begin
print("函数执行完成的时间",result)
return inner
@decorator
def work():
for i in range(10):
print(i)
3.通用装饰器的使用
通用装饰器:可以装饰任意类型的函数
格式:
def decorator(func):
def inner(*args, **kwargs):
...执行代码...
res = func(*args, **kwargs)
return res
return inner
示例:
import time
def wrapper(func):
def count(*args , **kwargs):
s_time = time.time()
func(*args,**kwargs)
e_time = time.time()
all_time = int(e_time - s_time)
print(f'这个程序一共花了{all_time}秒钟')
return count
ls = [0,6,16,26,36,46,56,66,76,86,96]
@wrapper # long_1 = wrapper(long_1)
def long_1(ll):
num = 0
for i in ll:
num += 1
print(i)
time.sleep(0.5)
print(f'列表的长度{num}')
long_1(ls)
4.多个装饰器的使用
多个装饰器的过程:由内到外的一个装饰过程,先执行内部的装饰器,在执行外部的装饰器
示例:
def make_d(func): # 外部装饰器
def inner():
res = "" + func() + ""
return res
return inner
def make_p(func): # 内部装饰器
def inner():
res = "" + func() + "
"
return res
return inner
@make_d
@make_p
def content():
return "人生苦短,我用Python"
res = content()
print(res)
执行结果:
人生苦短,我用Python
5.带有参数的装饰器
带有参数的装饰器介绍
带有参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数。
使用带参数的装饰器,其实就是在装饰器外面又包裹了一个函数,使函数接收参数,返回是装饰器,因为@符号需要配合装饰器使用。
语法:@装饰器名(参数1,……)
示例:
def return_decorator(flar):
def decorator(func):
def inner(*args,**kwargs):
if flar == "+":
print("正在执行加法运算")
elif flar == "-":
print("正在执行减法运算")
func(*args,**kwargs)
return inner
return decorator
@return_decorator("+")
def add(a,b):
res = a + b
print(res)
@return_decorator('-')
def sub(a,b):
res = a - b
print(res)
add(1,2)
sub(3,4)
带参数的装饰器其实就是定义了一个函数,让函数接收参数,在函数内部返回的是一个装饰器。
记住:装饰器只能接收一个参数并且是函数类型。
上一章:Python函数
下一章:Python中的模块与包



