闭包
简介
- 在函数内部再定义一个函数,内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包
- 优点:闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成
- 缺点:由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
- nonlocal访问外部函数的局部变量
def outer_func(number):
def inner_func(inner_number):
return number + inner_number
return inner_func
# 给外部函数复制,20传递给number,并返回内部函数
fun = outer_func(20)
print(fun(100)) # 120
print(fun(200)) # 220
装饰器
简介
- 装饰器本质上就是一个函数(或类),能够在不修改现有函数代码的情况下,对现有函数的功能实现扩充。
- 装饰器其实就是一个闭包,把一个函数当做返回参数。
- 装饰器:
- 装饰器为函数
- 被装饰对象为函数
- 无参装饰器
- 带参装饰器
- 被装饰对象为类
- 被装饰对象为函数
- 装饰器为类
- 被装饰对象为函数
- 被装饰对象为类
- 装饰器为函数
普通方式
def fun(test):
def inner():
print('inner')
test()
return inner
def fun1():
print('func1')
def fun2():
print('func2')
fun_test = fun(fun1)
fun_test()
fun_test = fun(fun2)
fun_test()
输出信息:
inner
func1
inner
func2
函数装饰器
无参装饰器
- @符号是 python 装饰器的语法,在定义函数的时候使用,避免再一次赋值操作
@outer func
等价于outer(func)
- 执行 func 函数实际上是执行 inner 函数的内容
def decorator(func):
def inner():
print('开始处理数据')
func()
print('数据处理完毕')
return inner
@decorator
def func():
print('正在处理数据')
func()
输出信息:
开始处理数据
正在处理数据
数据处理完毕
带参装饰器:被装饰对象带参
def decorator(func):
def inner(x, y):
print('开始处理数据')
result = func(x, y)
print('数据处理完毕')
return result
return inner
@decorator
def func(a, b):
print('正在处理数据')
return a * b
result = func(2, 3)
print(result)
输出信息:
开始处理数据
正在处理数据
数据处理完毕
6
带参装饰器:被装饰对象不定长参数
def decorator(func):
def inner(*args, **kwargs):
print("开始处理数据")
result = func(*args, **kwargs)
print("数据处理完毕")
return result
return inner
@decorator
def func1(a, b):
print('正在处理...')
return "%s-%s" % (a, b)
@decorator
def func2(a, b, c):
print('正在处理...')
return "%s,%s,%s" % (a, b, c)
result1 = func2('A', 'B', 'C')
print('返回数据:', result1)
result2 = func1("a", "b")
print('返回数据:', result2)
输出信息:
开始处理数据
正在处理...
数据处理完毕
返回数据: A,B,C
开始处理数据
正在处理...
数据处理完毕
返回数据: a-b
带参装饰器:装饰器带参
def decorator(arg): # 装饰器参数
def middle(func):
def inner(x, y):
print("开始数据处理")
x *= arg
y *= arg
result = func(x, y)
print("数据处理完毕")
return result
return inner
return middle
@decorator(10)
def func(a, b):
print('正在处理数据...')
return a * b
result = func(3, 4)
print(result)
输出信息:
开始数据处理
正在处理数据...
数据处理完毕
1200
类装饰器
__init__
初始化操作__call__
装饰器调用时操作
class Decorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('开始处理数据')
self.func()
print('数据处理完毕')
@Decorator
def fun():
print('数据处理中。。。')
fun()
输出信息:
开始处理数据
数据处理中。。。
数据处理完毕
functools.wraps()
- 使用装饰器时,有一些细节需要被注意。例如,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变)。
- 添加后由于函数名和函数的doc发生了改变,对测试结果有一些影响
例如:
def decorator(func):
def inner():
"""
inner函数
:return:
"""
pass
return inner
@decorator
def func():
"""
被装饰函数
:return:
"""
pass
print(func.__name__)
print(func.__doc__)
输出信息:
inner
inner函数
:return:
由此可见,被装饰的func的函数信息丢失了,解决这个问题可以使用functools.wraps()
函数
扫描二维码关注公众号,回复:
2747775 查看本文章
import functools
def decorator(func):
# func的属性绑定
@functools.wraps(func)
def inner():
"""
inner函数
:return:
"""
pass
return inner
@decorator
def func():
"""
被装饰函数
:return:
"""
pass
print(func.__name__)
print(func.__doc__)
输出信息:
func
被装饰函数
:return:
未完待续。。。