装饰器的作用
在不改变原有函数的源代码的情况下,给函数增加新的功能
装饰器的功能特点:
不修改已有函数的源代码
给已有函数增加额外的功能
# 1.定义一个装饰器(装饰器的本质是闭包)
def check(fn):
def inner():
print("登录验证。。。")
fn()
return inner
# 需要被装饰的函数
def comment():
print("发表评论")
# 2.使用装饰器装饰函数(增加一个登录功能)
comment = check(comment)
comment()
结果:
登录验证。。。
发表评论
装饰器流程图
装饰器语法糖
# 1.定义一个装饰器(装饰器的本质是闭包)
def check(fn):
def inner():
print("登录验证。。。")
fn()
return inner
# 2.使用装饰器装饰函数(增加一个登录功能)
# 解释器遇到@check会立即执行comment = check(comment)
@check
def comment():
print("发表评论")
comment()
结果:
登录验证。。。
发表评论
案例使用:
import time
# 1 定义装饰器
def get_time(fn):
def inner():
start = time.time()
fn()
end = time.time()
print("消耗时间:", end-start)
return inner
@get_time
def func():
for i in range(1, 10):
print(i)
func()
结果:
1
2
3
...
997
998
999
消耗时间: 0.00500035285949707
装饰带有参数的函数
def logging(fn):
def inner(a, b):
fn(a, b)
return inner
@logging
def sum_num(a, b):
result = a + b
print(result)
sum_num(1, 2)
# 打印输出
# 3
装饰带有返回值的函数
def logging(fn):
def inner(a, b):
result = fn(a, b)
return result
return inner
@logging
def sum_num(a, b):
result = a + b
return result
result = sum_num(1, 2)
print(result)
# 打印结果
# 3
装饰带有不定长参数的函数
def logging(fn):
def inner(*args, **kwargs):
result = fn(*args, **kwargs)
return result
return inner
@logging
def sum_num(*args, **kwargs):
print(args, kwargs)
sum_num(1,2,3, age='13')
# 打印结果
# (1, 2, 3) {'age': '13'}
多个装饰器的使用
# 定义装饰器1
def check1(fn1):
def inner1():
print("登录验证1")
fn1()
return inner1
# 定义装饰器2
def check2(fn2):
def inner2():
print("登录验证2")
fn2()
return inner2
# 被装饰的函数
@check1
@check2
def comment():
print("发表评论")
comment()
# 打印结果
# 登录验证1
# 登录验证2
# 发表评论
多个装饰器装饰函数时,规律是从下到上装饰函数,然后从上到下执行。
带参数的装饰器
# 装饰器
def logging(flag):
# 外部函数
def decorator(fn):
# 内部函数
def inner(num1, num2):
# 判断流程
if flag == '+':
print("--正在努力加法计算--")
elif flag == '-':
print("--正在减法计算--")
result = fn(num1, num2)
return result
return inner
# 返回装饰器
return decorator
# 被带有参数的装饰器装饰的函数
@logging('+')
def add(a, b):
result = a + b
return result
# 执行函数
result = add(1, 3)
print(result)
# 打印结果
# --正在努力加法计算--
# 4
类装饰器
__call__方法的使用
一个类里面一旦实现了__call__方法
那么这个类创建的对象就是一个可调用对象,可以像调用函数一样进行调用
# 定义一个类,实现__call__方法
class Check(object):
def __call__(self, *args, **kwargs):
print("我是call方法")
c = Check()
c()
# 打印结果
# 我是call方法
类装饰器使用
class Check(object):
def __init__(self, fn):
self.__fn = fn
def __call__(self, *args, **kwargs):
print("登录")
self.__fn()
# 被装饰的函数
@Check
def comment():
print("发表评论")
comment()
# 打印结果
# 登录
# 发表评论
**总结:**想要让类的实例对象能够像函数一样进行调用,需要在类里面使用call方法,把类的实例变成可调用对象。类装饰器装饰函数功能在call方法里面进行添加。