一、装饰器
装饰器:装饰函数和类,作用:扩展增加函数和类的功能
二、装饰器的分类
两大类:装饰器函数和装饰器类
三、装饰器函数定义及应用
函数: 封装代码最小单元,提供代码复用性
- 装饰器函数利用函数的一些特征:
-
-
函数可以用为参数;
-
函数可以作为变量;
-
函数也可以返回函数;
-
- 装饰器函数可以装饰所有的函数(有参数,没参数)
import time
def runTime(func):
"""
装饰函数
原来功能 + 扩展的功能: 统计每个函数的耗时
:param func:
:return:
"""
def wrapper(*args,**kwargs):
start = time.time()
#原来功能
func(*args, **kwargs)
end = time.time()
cost = end - start
print(f"统计函数使用时长:{func.__name__}耗时{cost}s")
return wrapper
@runTime
def test_no_params():
print("这是一个无参数的装饰器测试")
@runTime
def test_have_params(*args,**kwargs):
sum = 0
for num in args:
sum += num
print(f"求和: {sum}")
return sum
test_no_params()
test_have_params(2,4,3,5,6,8,9)
四、装饰器类
装饰器类的实质:
调用装饰类中的__call__内置函数
import time
#定义装饰器类 ------>本质类 作用: 原来功能 + 扩展功能
class Dec:
#原来功能 self._func()
def __init__(self,func):
self._func = func
#扩展功能
def __call__(self, *args, **kwargs):
"""
__call__函数: 实例化对象()
:param args:
:param kwargs:
:return:
"""
start = time.time()
#原来功能
self._func()
end = time.time()
cost = end - start
print(f"该函数{self._func.__name__}耗时: {cost}s")
return cost
@Dec
def test_no_param():
"""被装饰器函数"""
print("测试函数无参数")
time.sleep(2)
@Dec
def test_have_param(*args,**kwargs):
"""被装饰器函数"""
sum = 0
for i in args:
sum += i
print(f"sum函数耗时: {sum}s")
time.sleep(1)
print(test_no_param())
print(test_have_param([1,4,6,3,7,9]))
五、装饰器应用场景
常见的场景:授权及日志的收集、认证等
"""
1、编写装饰器,为多个函数加上认证的功能,要求登录成功一次,后续的函数都无需再输入用户名和密码
"""
FALG = False
def login(user,passwd):
with open(file='admin',mode='r',encoding='utf-8') as f:
if f.readline().strip() == user and f.readline().strip() == passwd:
return True
return False
def certification(func):
def wrapper(*args, **kwargs):
global FALG
if FALG:
res = func(*args, **kwargs)
else:
user = input("请输入用户名:")
password = input("请输入密码: ")
if login(user,password):
print("登录成功")
res = func(*args, **kwargs)
FALG = True
else:
print("登录失败")
return
return res
return wrapper
@certification
def shop_add():
print("增加一个商品")
@certification
def shop_del():
print("删除一个商品")
shop_add()
shop_del()
"""
2.编写装饰器,为多个函数加上记录调用功能,要求每次调用都将被调用的函数名写入文件
"""
def log(func):
def wrapper(*args, **kwargs):
with open(file="admin", mode="a", encoding="UTF-8") as file:
file.write(func.__name__ + '
')
res = func(*args, **kwargs)
return res
return wrapper
@log
def shop_1():
print("这是商店1")
@log
def shop_2():
print("这是商店2")
shop_1()
shop_2()
六、反射
把字符串映射到实例的变量或者实例的方法,然后可以进行调用、修改操作
反射四个重要的方法:
-
getattr 获取运动象属性/方法
-
hasattr 判断对象是否有对应的属性
-
delattr 删除指定属性
-
setattr 为对象设置内容