关于闭包:使用了外部函数变量的内部函数
使用闭包函数的目的:保存函数内的变量,而不会随着函数调用完而被摧毁
# 用于求和的闭包, 外部函数有参数num1, 内部函数有参数num2, 然后调用, 求两个整数和
# 1. 定义外部函数.
def func_outer(num1):
# 2. 定义内部函数
def func_inner(num2):
# 3. 求和.
sum = num1 + num2
print(f'求和结果为: {sum}')
# 4. 返回内置函数名.
return func_inner
# 5. 调用func_outer函数
my_fn = func_outer(3) # 等价于: my_fn = func_inner
my_fn(5)
>> 8
my_fn(6)
>> 9
有一种调用闭包函数的特殊写法,以上述函数为例:
func_outer(10)(20)
>> 30
介绍一下与之相关的两个函数global,noolocal:
global :在函数中使用,更改全局变量
# 定义变量
a = 1
# 定义函数
def fun_outer():
# 更改全局变量
global a
a = 100
print(a)
# 3. 调用函数.
fun_outer()
>> 100
noolocal :在内部函数中使用,更改外部函数的变量
# 1. 定义外部函数
def fun_outer():
# 定义外部函数的变量
a = 100
# 2. 定义内置函数.
def fun_inner():
nonlocal a
print(f'a的值为: {a}')
return fun_inner
# 3. 调用函数.
my_fun = fun_outer()
my_fun()
noolocal在闭包函数中可以作为累加器计算:
# 1. 定义外部函数
def fun_outer():
# 定义外部函数的变量
a = 100
# 2. 定义内置函数.
def fun_inner():
nonlocal a
a = a + 1
print(f'a的值为: {a}')
return fun_inner
# 3. 调用函数.
my_fn = fun_outer()
my_fn()
>> a的值为: 101
my_fn()
>> a的值为: 102
my_fn()
>> a的值为: 103
关于装饰器:实际上就是一个闭包函数
装饰器的产生是为了不改变原有的函数,而给这个函数添加新的功能
# 1. 定义装饰器.
def print_info(fn_name): # fn_name: 表示要被装饰的函数名
def fn_inner(): # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致.
print('[友好提示] 正在努力计算中...')
fn_name()
return fn_inner
# 2. 定义原函数(即: 要被装饰的函数)
@print_info # 这个是语法糖写法, 等价于: get_sum = print_info(get_sum)
def get_sum():
a = 10
b = 20
sum = a + b
print(f'求和结果为: {sum}')
# 3. 调用原函数.
get_sum()
使用装饰器时要注意:内置函数的格式要与原函数(被调用函数)格式保持一致即参数与返回值保持一致。
同一个函数可以被多个装饰器同时装饰
# 1. 定义装饰器, 实现: 登录用户
def check_user(fn_name):
def inner():
print('--- 我在登陆账号, 校验登陆 ---')
fn_name()
return inner
# 2. 定义装饰器, 实现: 验证码校验
def check_code(fn_name):
def inner():
print('--- 验证码验证! ---')
fn_name()
return inner
# 3. 定义函数, 实现: 评论功能.
@check_user
@check_code
def comment():
print('我来发表评论了...')
# 4. 调用, 语法糖形式.
comment()
总结一下:
闭包函数需满足三个条件:有嵌套,有引用(在内部函数使用了外部函数的变量),有返回(外部函数中返回了内部函数)
装饰器:是一个闭包函数,同时满足要有新加的功能,并且内置函数与原函数格式保持一致。