闭包与装饰器
[toc]
1. 函数作为参数
# 函数定义的时候 ,函数内部的代码是不会执行 函数名 func_01 存储的是一个 内存 地址 0x1111
def func_01():
print("我是函数 func_01, 这是我输出的内容.......")
# 函数定义的时候 ,函数内部的代码是不会执行 函数名 func_02 存储的是一个 内存 地址 0x2222
# 此函数有一个 形参 func , 后续要去接收 实参的值
def func_02(func):
# 实参的值会传递给 形参, 将 func = 0x1111, 也就表示 现在的func 其实就是 func_01这个函数了
print(func) # 先输出的是 函数的地址
func() # 去调用了 函数 func_01()
# 调用 函数 func_02 ,并且传递了一个实参, func_01 ---> 0x1111 相当于 func_02(0x1111)
func_02(func_01)
1.1 结论
2. 闭包
闭包使用场景:我们前面已经学过了函数,我们知道当函数调用完,函数内定义的变量都销毁了,但是我们有时候需要保存函数内的这个变量,每次在这个变量的基础上完成一系列的操作,比如: 每次在这个变量的基础上和其它数字进行求和计算,那怎么办呢?我们就可以通过咱们今天学习的闭包来解决这个需求。
闭包的作用:
闭包可以保存函数内的变量,不会随着函数调用完而销毁
2.1 形成闭包的条件
- 函数嵌套的定义(在一个函数中又定义了另外一个函数)
- 内部函数使用外部函数的变量(外部函数的定义的变量,或者是外部函数的参数)
- 外部函数要返回内部函数的函数名(内部函数的引用地址)
2.2 闭包的定义
# 1. 函数嵌套的定义(在一个函数中又定义了另外一个函数)
# 2. 内部函数使用外部函数的变量(使用的变量:外部函数的定义的变量,或者是外部函数的参数)
# 3. 外部函数要返回内部函数的函数名(内部函数的引用地址)
def func_out(name): # 这个name也是属于外部函数的变量
# 属于外部函数 func_out 变量
num = 100
def func_inner():
# 内部函数inner 中使用了 外部函数 out 的num 这个变量的数据
print(f'外部函数的数据num是: {num}')
return func_inner
2.3 闭包的流程图
# 1. 函数嵌套的定义(在一个函数中又定义了另外一个函数)
# 2. 内部函数使用外部函数的变量(使用的变量:外部函数的定义的变量,或者是外部函数的参数)
# 3. 外部函数要返回内部函数的函数名(内部函数的引用地址)
def func_out(): # 这个name也是属于外部函数的变量
# 属于外部函数 func_out 变量
num = 100
def func_inner():
# 内部函数inner 中使用了 外部函数 out 的num 这个变量的数据
print(f'外部函数的数据num是: {num}')
return func_inner
# 上述代码中 就是闭包函数,那么这个闭包函数 跟普通函数调用是一样。
# 函数名()
f = func_out() # 现在我们在调用 func_out 函数,这个函数是有返回值的,返回的是内部函数 inner 的内存地址 现在的 f 就是内部函数
f()
3. 装饰器
3.1 装饰器的作用和定义
装饰器的作用:在不改变原有函数代码的基础上,给函数增加新的功能。
装饰器的语法: 装饰器函数在定义的时候 ,本质就是一个闭包, 使用的时候
- 使用 语法糖的方式, @闭包函数名
- f = 闭包函数(被装饰函数的函数名)
3.2 装饰器的执行流程
3.3 装饰器装饰带有返回值的函数
# 定义一个闭包
def func_out(func):
def func_inner():
print("进行登录操作,登录成功...")
return func()
return func_inner
@func_out
def user_center():
return "用户中心....."
# 还是刚才的需求,不改变原来user_center代码基础上, 去实现让用户先进行登录,再访问个人中心操作
res = user_center() # 执行这一句话的时候,相当于在执行 func_inner,因为func_inner中没有写return,
print(res)
3.4 装饰器装饰带有参数的函数
def func_out(func):
def func_inner(*args, **kwargs):
print(f"{args} ---{kwargs}登录成功了")
return func(*args, **kwargs)
return func_inner
@func_out
def user_center(*args, **kwargs):
return f"{args} ---{kwargs} 欢迎你访问个人中心"
res = user_center("张三", 19, "男", a=10, b=30, c=40)
print(res)
3.5 装饰器带参数
def foo(num):
def func_out(func):
def func_inner():
print(f"登录成功.{num}....")
func()
return func_inner
return func_out
"""
@func_out
def user_center():
pass
这个地方:user_center = func_out(user_center) ==> @func_out
@foo ==> 先去执行 foo(100) ---> func_out @foo = @func_out
"""
"""
@foo
@
foo(100) ---> 相当于去执行 foo函数 并且传了一个实参 100, 执行foo函数的时候
因为这个函数有返回值,返回值是, func_out. 相当于foo(100) == func_out
执行完foo之后,得到了 @func_out
@func_out
def user_center():
pass
user_center = func_out(user_center)
"""
@foo
def user_center():
print("个人中心....")
user_center()
闭包 和 装饰器
闭包的三个条件:
- 函数嵌套的定义(在一个函数中又定义了另外的一个函数)
- 内部函数使用了外部函数的变量
- 外部函数返回内部函数的引用
能掌握:能够自己去定义出来闭包函数,并且能够搞清楚闭包函数执行的流程。
装饰器:装饰器本质就是闭包,作用就是在不改变原有函数的基础上,给原函数增加功能、
使用: 先定义一个闭包函数,
在被装饰的函数的头上,加 @闭包函数名 ==> 被装饰的函数名 = 闭包函数名(被装饰的函数名)