1.函数装饰器的定义
在python中我们经常听到\看到一类函数A,在这类函数的定义声明(def)之前还有类似于@xxx的记号。对于这类函数A,我们称之为被修饰的函数,而对于 @中的xxx 我们称之为函数装饰器(function decorator)。
譬如说,对于如下代码片段。
# example:
def funcShell(func):
def decorator(**kws):
#**kws是指关键字参数 (keyword arguments),没什么卵用
print("decorator方法被使用!")
#lz直接把函数(function)叫成方法(method)了
#其实是一个事儿
return func(**kws)
return decorator
@funcShell
def funcInput():
print("funcInput方法被使用!")
return None #此处的return没用,可忽略
if __name__ == '__main__':
#主程序调用方法的标准格式,起到用来调式代码的作用
funcInput()打印结果如下:
decorator方法被使用!
funcInput方法被使用!
在上述代码中,funcShell就起到了函数装饰器的作用,被装饰的方法就是funcInput()。实际上的执行顺序为:funcShell(funcInput);所以我们看到结果才是先执行了funcShell中的打印语句,然后才执行了funcInput中的打印语句。
2.函数装饰器的作用
函数装饰器(decorator)最根本的最用在于“对现有程序的再利用”,说白了就是为了偷懒。虽然说人类的本质是复读机,但是偷懒还是人类的天性。为了最大程度上实现对现有程序的利用,如果只需要改变程序的输入或输出的部分步骤,而不需要对程序的主体进行修改,那就可以用到函数装饰器来偷懒。
分析上述代码之前,我们需要知道:传入函数(方法)中的参数不仅仅可以是一般类型或者引用类型的数据,甚至还可以是函数(方法)本身。例如,
def func_one(**kws):
print("func_one has been used!")
return None
def func_test(func):
func()
return None
if __name__ == '__main__':
func_test(func_one)在上述程序中,func_one函数就以参数(parameter)的形式传入到了func_test函数中。
同理,对于函数装饰器我们一样可以看作是把一个现成的函数传入到装饰器中去,并在该函数执行的前后空间内进行额外的操作,赋予原来函数还不具有的某些功能。
3.如何在类中定义函数装饰器?
lz曾经想在类中也定义装饰器,但是弄了很久才解决问题。主要的问题处在类中定义的方法相关的参数的传递上。以如下代码片段为例。
from functools import wraps
class Test(object):
def __init__(self):
print("初始化完成")
return None
def funcShell(func):
@wraps(func)
def decorator(self, **kws):
#**kws是指关键字参数 (keyword arguments),没什么卵用
print("decorator方法被使用!")
#lz直接把函数(function)叫成方法(method)了
#其实是一个事儿
return func(self, **kws)
return decorator
@funcShell
def funcInput(self):
print("funcInput方法被使用!")
return None #此处的return没用,可忽略
if __name__ == '__main__':
object_example = Test()
Test.funcInput()打印结果如下:
decorator方法被使用!
funcInput方法被使用!
结果与非类方法的一般方法定义所给出的结果是一致的。唯一需要注意的问题在于:对于类定义中的方法我们不需要在外层壳子Shell的参数中绑定self,只需要在wraps所定义的内层方法Kernal中加入self参数,同时在wraps所作用的decorator的返回值中给出形如输入函数(self, **kws)的形式,即可实现函数装饰器的功能。
这主要是因为,返回的装饰后的函数需要凭借self来提供一个类似于调用的接口。
4.结论
函数装饰器作为修改原有函数(方法)的偷懒神器,在提高人类社会生产效率的历史上留下了浓墨重彩的一笔。 :)
















