闭包
当调用完函数后,函数内定义的变量就销毁了,但有时需要保存函数内的这个变量,并在这个变量的基础上完成一系列的操作 ,那怎么办呢? 答案就是使用闭包!
作用:
闭包可以保存函数内的变量,而不会随着调用完函数而被销毁。
语法:
# 外部函数
def 外部函数名(外部参数):
# 内部函数
def 内部函数名(内部参数):
...[使用外部函数的变量]
return 内部函数名
构成条件:
①有嵌套:在函数嵌套(函数里面再定义函数)的前提下;
②有引用:内部函数使用了外部函数的变量(还包括外部函数的参数);
③有返回:外部函数返回了内部函数名。
应用场景----累加器:
"""
累加器
nonlocal:
外部函数的变量必须用nonlocal修饰,这样改变量才可以被内置函数修改
"""
# 1.定义外部函数
def func_outer(): # 有嵌套
# 2.定义外部函数变量
a = 100
# 3.定义内部函数
def func_inner(): # 有嵌套
# 核心细节:外部函数的变量必须用nonlocal修饰,这样改变量才可以被内置函数修改
nonlocal a
# 累加器动作 然后输出
a = a+1 # 有引用,引用外部函数变量
print(f'a的值为{a}')
# 4.返回内置函数
return func_inner # 有返回,返回内部函数名
# 调用func_outer函数
my_fn = func_outer() # 等价于: my_fn = func_inner
my_fn() # 101
my_fn() # 102
my_fn() # 103
装饰器
作用:
装饰器的作用是不改变原有函数的基础上,给原有函数增加额外功能。 装饰器本质上就是一个闭包函数。
构成条件:
①有嵌套:在函数嵌套(函数里面再定义函数)的前提下;
②有引用:内部函数使用了外部函数的变量(还包括外部函数的参数);
③有返回:外部函数返回了内部函数名;
④有额外功能:给需要装饰的原有函数增加额外功能。
四种场景写法:
"""
装饰器细节:
1. 装饰器的目的是: 在不改变原有函数的基上, 给原函数增加 额外功能
2. 装饰器常用与法主要是: 语法糖形式, 即: @装饰器名
3, 使用装饰器的小技巧: 保证装饰器的 内置函数格式 和 原函数(要被装饰的函数) 格式保持一致,都是无参无返回,无参有返回...
"""
# 场景一:无参无返回
# 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 = print_info(get_sum) # 原始写法, 看懂即可, 一般不用.
get_sum()
# 场景二:无参有返回
# 1.定义装饰器
def print_info(fn_name): # fn_name: 表示要被装饰的函数名
def fn_inner(): # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
print('正在努力计算中...')
return 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}')
return sum
# 3.调用函数
# get_sum = print_info(get_sum) # 原始写法, 看懂即可, 一般不用.
get_sum()
# 场景三:有参无返回
# 1.定义装饰器
def print_info(fn_name): # fn_name: 表示要被装饰的函数名
def fn_inner(a,b): # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
print('正在努力计算中...')
fn_name(a,b)
return fn_inner
# 2.定义原函数,(即: 要被装饰的函数)
@print_info # 这个是语法糖写法, 等价于: get_sum = print_info(get_sum)
def get_sum(a,b):
sum = a + b
print(f'求和结果为{sum}')
# 3.调用函数
# get_sum = print_info(get_sum) # 原始写法, 看懂即可, 一般不用.
get_sum(100,200)
# 场景四:有参有返回
# 1.定义装饰器
def print_info(fn_name): # fn_name: 表示要被装饰的函数名
def fn_inner(): # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
print('正在努力计算中...')
return 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}')
return sum
# 3.调用函数
# get_sum = print_info(get_sum) # 原始写法, 看懂即可, 一般不用.
get_sum()
# 场景四:有参有返回
# 1.定义装饰器
def print_info(fn_name): # fn_name: 表示要被装饰的函数名
def fn_inner(a,b): # 内置函数, 格式要和 原函数(被装饰的函数) 保持一致
print('正在努力计算中...')
return fn_name(a,b)
return fn_inner
# 2.定义原函数,(即: 要被装饰的函数)
@print_info # 这个是语法糖写法, 等价于: get_sum = print_info(get_sum)
def get_sum(a,b):
sum = a + b
print(f'求和结果为{sum}')
return sum
# 3.调用函数
# get_sum = print_info(get_sum) # 原始写法, 看懂即可, 一般不用.
get_sum(33,66)
带参数的装饰器:
"""
案例:
演示不带参数的装饰器.
目的:
演示1个装饰器 可以用来 装饰 多个函数
需求:
定义一个既能装饰减法运算, 又能装饰加法运算的装饰器, 即: 带有参数的装饰器
"""
# 1.定义装饰器
def logging(flag): # 有嵌套,接收:装饰器的参数 + -
def decorator(fn_name): # 有嵌套 接收原函数名
def inner(num1,num2): # 有嵌套 给函数增加额外功能
if flag =='+':
print('正在努力计算 加法 中...')
if flag =='-':
print('正在努力计算 减法 中...')
return fn_name(num1,num2)
return inner
return decorator
# 2.定义函数,加法运算
@logging('+')
def get_sum(a,b):
sum = a+b
return sum
# 3.定义函数,减法运算
@logging('-')
def get_sub(a,b):
sub = a-b
return sub
# 4.调用函数
sum = get_sum(10,7)
print(f'相加为{sum}')
sub = get_sub(10,7)
print(f'相减为{sub}')