什么是装饰器
python装饰器实际上就是一个函数,它可以让已经实现的函数在不需要在原代码上做任何代码的处理的前提下增加额外的功能,装饰器的返回值也是一个对象。
装饰器应该遵循以下原则:开放和封闭。
- 开放:对现有功能的扩展开放
- 封闭:已实现的功能代码不应该被修改
实现装饰器的先导知识
函数嵌套
函数嵌套就是在一个函数中可以定义函数。同样在函数内部可以调用在函数中定义的函数。
def outer_func():
print("This is an outer function.")
def inner_func():
print("This is an inner function.")
inner_func()
outer_func()
# output
# This is an outer function.
# This is an inner function.
闭包
出现在嵌套函数中,指的是在一个外层函数中定义了一个内层函数,内层函数里运用了外层函数的临时变量,并且外层函数的返回值是内层函数的引用,这样就构成了一个闭包。
def outer_func():
outer_data = 5
def inner_func():
print("外层数据是:", outer_data)
return inner_func
inner = outer_func()
inner()
# output
# 外层数据是: 5
高阶函数
一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数,满足其一则为高阶函数。
# 参数为函数
def test():
print("in function test")
def test1(func):
func()
print("in function test1")
test1(test)
# output
# in function test
# in function test1
# 返回值为函数
def test():
print("in function test")
def test1():
print("in function test1")
return test
ret = test1()
ret()
# output
# in function test1
# in function test
函数装饰器
装饰器=高阶函数+函数嵌套+闭包
无参函数装饰器
下面是最简单的装饰器的例子:
import time
def foo(func):
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print("函数运行时间:", end_time - start_time)
return wrapper
@foo
def test():
time.sleep(1)
print("Test")
test()
# output
# Test
# 函数运行时间: 1.014491319656372
有参函数装饰器
上面的装饰器只能装饰没有形参的函数。要定义的函数有参数则需要以下定义方式:
#具体例子
def wrap(func):
def wrapper(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
stop_time = time.time()
print("共耗时:", stop_time - start_time)
return wrapper
@wrap
def add(a, b):
time.sleep(1)
print(a + b)
add(5, 2)
# output
# 7
# 共耗时: 1.0005483627319336
有返回值函数装饰器
若要装饰的函数有返回值,则需要以下定义方式:
def wrap(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print("共耗时:", stop_time - start_time)
return res
return wrapper
@wrap
def add(a, b):
time.sleep(1)
return a + b
result = add(5, 2)
print("结果是:", result)
# output
#共耗时: 1.0000336170196533
#结果是: 7
完整装饰器框架
def wrap(func):
def wrapper(*args, **kwargs):
"""可增加的功能"""
res = func(*args, **kwargs)
return res
return wrapper
带参数的装饰器
待更新。。。