Python高阶函数之装饰器
1
高阶函数的概念
高阶函数的概念:满足下面两个条件之一就可以称之为高阶函数。
1、接收一个或者多个函数作为参数。
2、将函数作为返回值进行返回。
# 将函数作为返回值返回也是一种高阶函数-闭包。
2
装饰器的概念
装饰器就是用于拓展函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数代码的前提下给原函数增加新的功能。
3
进入操作
首先我们先定义两个函数;
def add(a,b):# 此函数用于两个数字的加法运算return a + bprint(add(5,6))# output:11def mul(a,b):# 从函数用于两个数字的乘法运算return a * bprint(mul(5,6))# output: 30
# 对于结果显得难免有些单调,我们可以在函数中加一些提示语,例如在计算函数前打印“开始执行函数。”在函数执行结束后打印“函数执行结束。”
def add(a,b):# 此函数用于两个数字的加法运算print("开始执行函数")r = a + bprint("函数执行结束")return rprint(add(5,6))# ouput:# 开始执行函数# 函数执行结束# 11def mul(a,b):# 从函数用于两个数字的乘法运算print("开始执行函数")r = a * bprint("函数执行结束")return rprint(mul(5,6))# output:# 开始执行函数# 函数执行结束# 30
# 问题:通过修改以上函数发现了一些问题:
1、如果要修改的函数过多,那么修改起来就比较麻烦。
2、不易于后期维护,例如将“开始执行函数”改为“函数开始执行”那么你将要进行全部更新。
3、会违反ocp开闭原则。
# 开闭原则中“开”,是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的;开闭原则中“闭,是指对于原有代码的修改是封闭的,即不应该修改原有的代码。
那么我们又该如何在不修改原函数的条件下去扩展该函数的功能呢?
请往下看。
def add(a,b):# 此函数用于两个数字的加法运算print(a + b)def speak():# 此函数用于打印提示print("开始执行函数")add(5,6)print("函数执行结束")speak()# output:# 开始执行函数# 11# 函数执行结束
# 问题:把需要扩展的函数进行内嵌倒是可以实现对该函数的扩展,达到增加额外功能的需求,但是如果要扩展的函数过多呢?难不成要写多个函数进行扩展吧?所以接下来我们的主角登场了,它就是装饰器!
# 这是一个装饰器函数def hint(func):# 此函数用于打印提示def wrapper():print("开始执行函数.")func()print("函数执行结束.")return wrapper@hintdef speak():print("你好Python!")speak()# ouput:# 开始执行函数.# 你好Python!# 函数执行结束.
总结:这里的hint函数就是最原始的装饰器,它的参数是一个函数,然后返回值也是一个函数。其中作为参数的这个函数func()就在返回函数wrapper()的内部执行。然后在函数speak前面加上@hint,speak()函数就相当于被扩展了提示功能,现在只要调用speak(),它就已经变身为“新的功能更多”的函数了。
所以这里装饰器就像一个注入器,有了它,拓展原来函数的功能既不需要侵入函数内更改代码,也不需要重复执行原函数了。
# 问题:如果需要扩展函数需要传参怎么办?例如以下函数:
# 这是一个装饰器函数def hint(func):# 此函数用于打印提示def wrapper():print("开始执行函数.")func()print("函数执行结束.")return wrapper@hintdef add(a,b):return a + badd(5,6)# ouput:TypeError: wrapper() takes 0 positional arguments but 2 were given# 报错:wrapper()函数缺少两个位置参数
解决办法如下:
# 这是一个装饰器函数def hint(func):# 此函数用于打印提示def wrapper(*args,**kwargs):print("开始执行函数.")func(*args,**kwargs)print("函数执行结束.")return wrapper@hintdef add(a,b):print(a + b)add(5,6)# ouput:# 开始执行函数.# 11# 函数执行结束.
是不是已经解决了?
到这里相信你已经对装饰器有一定的了解了,接下来我们来进行个有趣的关于装饰器的实验。
import time# 导入时间模块def wrappers(func):# 这是一个装饰器函数def timer(*args,**kwargs):# 这是一个计时器函数start_time = time.time()# 在当前时间打上时间戳--开始时间print("开始执行[{}]函数。".format(func.__name__))func(*args,**kwargs)end_time = time.time()# 在当前时间打上时间戳--结束时间use_time = end_time - start_time# 使用时间 等于 结束时间 减去 开始时间 ,单位为秒print("函数执行结束,用时%ds"%use_time)return timer@wrappersdef hint():# 此函数用来打印你好,python!print("你好")time.sleep(1) # 休眠一秒print("python!")hint()# output:# 开始执行[hint]函数# 你好# python!# 函数执行结束,用时1s
有没有为装饰器感到强大? 哈哈
我们下回再见~
记得“在看”哦~
可以加小编微信我们进行互动啊~~