函数的进阶—闭包
闭包的定义:嵌套函数,内部函数调用外部函数的变量。满足这个条件就算闭包。
闭包案例演示:
def outer(): a = 1 def inner(): print('inner函数中打印的变量a:',a) # 嵌套函数中使用了外层函数的变量。此时满足了闭包的条件。 return inner # 常用的方式,将inner的内存地址作为返回值,可以在外部直接调用inner,并且inner可以使用外层的变量:a。从而延长了变量a的生命周期 inn = outer() print('打印inn', inn) # 打印结果为inner函数的内存地址 inn() # 内存地址+(),即表示调用inner这个函数 输出内容: 打印inn <function outer.<locals>.inner at 0x0000028217752670> inner函数中打印的变量a: 1
函数的进阶-装饰器
装饰器的作用
主要作用是在不修改原始函数的情况下,为其增加额外的功能。应用于日志功能:记录函数的调用;性能测试:统计函数执行的时间等...
完整的装饰器固定写法
1.0版本-不使用语法糖的写法(为了便于理解)
# 装饰器的固定写法(不使用语法糖得版本,为了便于理解) # 定义一个装饰器函数 def wrapper(func): # 接收被装饰函数的函数名(内存地址) def inner(*args, **kwargs): # 这俩可变参数可以兼容所有参数类型的函数 print("在被装饰函数之前要做的事情") ret = func(*args, **kwargs) # 调用被装饰函数,并接收返回值 print("在被装饰函数之后要做的事情") return ret # 将被装饰函数的返回值,返回给调用者 return inner # 被装饰的函数 def func(a, b): print("被装饰的函数") print("打印两个参数:", a, b) func = wrapper(func) func(1, 2) # 调用func演示
2.0版本-使用语法糖的写法
# 装饰器的固定写法(使用语法糖) # 定义一个装饰器函数 def wrapper(func): # 接收被装饰函数的函数名(内存地址) def inner(*args, **kwargs): # 这俩可变参数可以兼容所有参数类型的函数 print("在被装饰函数之前要做的事情") ret = func(*args, **kwargs) # 调用被装饰函数,并接收返回值 print("在被装饰函数之后要做的事情") return ret # 将被装饰函数的返回值,返回给调用者 return inner # 被装饰的函数 @wrapper # @wrapper 等价于 func = wrapper(func) 。使用@wrapper语法糖把函数加上装饰器 def func(a, b): print("被装饰的函数") print("打印两个参数:", a, b) func(1, 2) # 调用func演示
语法糖是什么:本质上,语法糖是对已有语法结构的封装或简化,让开发者用更简洁的方式表达复杂的逻辑。(引用于ChatGPT)
在python中有些功能使用了语法糖特性?
- Lambda 表达式
- 装饰器
- 三元表达式
- 解包赋值
3.0版本-使用@wraps装饰器,解决被装饰函数无法获取真实的函数名问题
背景:使用函数名.__name__可以获取函数的函数名。但是如果按照前面的写法,将无法获取被装饰函数的真实函数名,实际拿到的是装饰器函数的方法名。代码说明:
def func1_name(): pass print(func1_name.__name__) # 打印出func1_name函数的函数名 输出结果: func1_name
# 定义一个装饰器函数 def wrapper(func): def inner(*args, **kwargs): print("在被装饰函数之前要做的事情") ret = func(*args, **kwargs) print("在被装饰函数之后要做的事情") return ret return inner # 被装饰的函数 @wrapper def func(a, b): print("被装饰的函数") print("打印两个参数:", a, b) print(func.__name__) 输出结果: inner # func是被装饰的函数,按理说我们的需求打印出的应该是"func",也就是函数本身的方法名。现在的执行结果却是"inner"(装饰器内部嵌套函数的方法名)。 # 为了解决获取不到被装饰函数的真实函数名问题,则需要使用functools中的@wraps装饰器,装饰在装饰器的内部方法上 from functools import wraps def wrapper(func): @wraps(func) # 装饰器内部函数增加@wraps方法装饰后,就支持查看被装饰函数真实的函数名 def inner(*args, **kwargs): print("在被装饰函数之前要做的事情") ret = func(*args, **kwargs) print("在被装饰函数之后要做的事情") return ret return inner # 被装饰的函数 @wrapper def func(): print("被装饰的函数") print(func.__name__) # 打印被装饰函数的函数名 输出结果: func
4.0版本-三层嵌套的装饰器,支持装饰器传参,可以用传入标志位来控制装饰器是否生效
标签:闭包,函数,17,生成器,inner,func,print,装饰,def From: https://www.cnblogs.com/mingbo-1/p/18472729