修饰器(Decorator)
decorator就是一个返回函数的高阶函数,,它的用法就是使用@符号,后面跟着修饰器名称,放在需要修饰的方法上面
# 修饰器
import functools # 导入functools模块
def decorator(fun): # 修饰器都会有一个参数:函数
@functools.wraps(fun) # 作用:将fun函数属性赋值到calculation函数中,保证被修饰后的函数属性还是原来那个函数
def calculation(*args, **kw):
num = 0
for x in args:
num = num + int(x)
print 'funName: %s' % fun.__name__ + ' total:%d'%num
return fun(*args, **kw) # 修饰器内部最后都是返回被修饰的函数执行
return calculation
@decorator # 修饰器用法,将@<修饰器名称> 置于函数上方声明,表示该函数被一个修饰器修饰了(好处:可以在不用修改原本函数前提下,动态的在函数执行前执行自己设计的代码)
def logName(*number):
print 'Pocket'
logName(1,2,3)
logName()
'''
每个函数都有一个__name__属性,表示函数的名字.
如果不加@functools.wraps(fun)代码,可以看被修饰后函数名称已经改变成calculation,
所以我们需要借助functools模块将其原始函数属性赋值到calculation函数中
'''
print logName.__name__
'''
运行结果
funName: logName total:6
Pocket
funName: logName total:0
Pocket
logName
'''
# 带参数的修饰器
def logText(text):
def decoratorText(fun):
@functools.wraps(fun)
def textFun(*args, **kw):
print text
return fun(*args, **kw) # 修饰器内部最后都是返回被修饰的函数执行
return textFun
return decoratorText
@logText('爱你一万年') # 使已经被定义的函数不要再次更改就能达到自己想要的运行效果
def test():
print 'Baby'
'''
嵌套拆解:
test() => logText('爱你一万年')(test) # 被修饰后,把他看成这种效果:logText('爱你一万年')(test)
1.decoratorText = logText('爱你一万年') # text传递进去了,返回decoratorText函数
2.textFun = decoratorText(test) # test函数传递进去,返回textFun函数,因为@functools.wraps(fun)作用,导致返回的textFun函数名称其实就是test函数名称
3.textFun() # print text; print 'Baby'
'''
test()
print test.__name__
'''
运行结果
爱你一万年
Baby
test
'''