装饰器
我们现在想要在程序中定义两个函数,分别用类打印九九乘法表和计算N以内的数字累加的和。
# 定义功能: 打印九九乘法表
def print_nine_table():
for line in range(1, 10):
for column in range(1, line + 1):
print(f"{column} * {line} = {column * line}", end="\t")
print()
# 定义功能,完成N以内的数字的计算
def get_sum(n):
sum = 0
for i in range(1, n + 1):
sum += i
print(sum)
现在来了个需求,我需要统计九九乘法表的方法需要执行多长时间!
time_start = time.time()
print_nine_table()
time_end = time.time()
print(f"任务耗时: {time_end - time_start}")
一个函数的执行时间统计可以这样去统计,可是如果是多个函数呢?例如有10个函数,都需要统计计算时间改怎么办?是不是需要重复的去定义time_start、time_end以及去计算差值呢?其实没有必要,我们只需要将这些重复的部分单独提取出来即可。那么中间需要执行的参数怎么办?可以使用函数参数来实现。
def get_function_time(function, *args, **kwargs):
time_start = time.time()
result = function(*args, **kwargs)
time_end = time.time()
print(f"任务耗时: {time_end - time_start}")
return result
get_function_time(print_nine_table)
get_function_time(get_sum, 10)
基本的功能解决了,如果想要通过调用原来函数的名字,既能实现原来的功能,又能统计消耗的时间,又该怎么做呢?例如: print_nine_table() 既能打印九九乘法表,又能打印消耗的时间。此时就需要新建一个变量,用来临时存储之前的功能。
other = print_nine_table
print_nine_table = get_function_time
print_nine_table(other)
other = get_sum
get_sum = get_function_time
get_sum(other, 20)
此时又出现了重复的操作: 定义第三方变量,赋值、调用,因此,能不能把这个过程再简化一下?
def transform(func):
return get_function_time
print_nine_table = transform(print_nine_table)
print_nine_table(get_sum, 10)
此时出现问题,如果我将transform的返回值使用print_nine_table接收,那么就不能求print_nine_table本身的时间了。
如何在函数A中,获取到函数B的数据?嵌套函数!
def transform(func):
def get_function_time(*args, **kwargs):
time_start = time.time()
result = func(*args, **kwargs)
time_end = time.time()
print(f"任务耗时: {time_end - time_start}")
return result
return get_function_time
print_nine_table = transform(print_nine_table)
print_nine_table()
get_sum = transform(get_sum)
get_sum(20)
终于写完了,但是太麻烦了!
# Python提供了@语法糖的替换操作!
# 相当于 test_transform = transform(test_transform)
@transform
def test_transform():
print("test_transform")
"""
装饰器案例:
APP中有点赞、评论等操作,
设计装饰器,在执行点赞、评论操作的时候,先让用户登录,登录成功可以继续操作
"""
def login_check(func):
def inner(*args, **kwargs):
username = input("请输入用户名: ")
password = input("请输入密码: ")
if username == "shawn" and password == "123456":
func(*args, **kwargs)
else:
print("登录失败,再见!")
return inner
@login_check
def comment(content):
print(f"发布评论: {content}")
comment("HAHAHA")