1、装饰器是函数的封装
def decorator(fn):
def wrapper():
print('%s' %fn.__name__)
fn()
print('%s' %fn.__name__)
return wrapper()
@decorator
def fun():
print("I am fun!!!")
fun()
#输出
fun
I am fun!!!
fun
1) 函数前面有@decorator注解,decorator就是前面定义的函数
2) decorator函数返回了wrapper函数,在wrapper函数里面回调了fun函数
本质流程如下
@decorator
def fun():
print(“I am fun!!!”)
变成了
fun = decorator(fun)
就是把一个函数传递到另一个函数中,再回调了自己
2、可以给函数加上多个decorator
@decorator_one
@decorator_two
def fun():
print("I am fun!!!")
# 这样就成了
fun = decorator_one(decorator_two(fun))
3、可以给decorator添加参数
@decorator(arg1,arg2)
def fun():
print("I am fun!!!")
# 这样就成了
fun = decorator(arg1,arg2)(fun)
一个网页编程的例子:
def makeHtml(tag, *args, **kwargs):
def real_decorator(fn):
css_class = "class='{0}'".format(kwargs['cssClass']) if 'cssClass' in kwargs else ''
def wrapper():
return '<'+tag+" "+css_class+'>'+fn()+'</'+tag+'>'
return wrapper
return real_decorator
@makeHtml(tag='b', cssClass='bold_css')
@makeHtml(tag='i', cssClass='item')
def func():
return 'hello world'
print(func())
#输出
<b class='bold_css'><i class='item'>hello world</i></b>
# 代码解释:
当调用func()的时候相当于执行了代码func = makeHtml(makeHtml(func))
1.首先先调用里层的makeHtml(func),此时会回调real_decorator将func函数传进去
此时会回调wrapper,wrapper里面会回调func函数
2.当执行到外层的makeHtml函数时候,再次回调real_decorator将1执行的结果传进去
此时回调wrapper,wrapper里面会回调1中的执行结果
使用类的方式实现上述案例:
class makeHtmlTagClass(object):
def __init__(self, tag, css_class=""):
self._tag = tag
self._css_class = " class='{0}'".format(css_class) \
if css_class !="" else ""
def __call__(self, fn):
def wrapped(*args, **kwargs):
return "<" + self._tag + self._css_class+">" \
+ fn(*args, **kwargs) + "</" + self._tag + ">"
return wrapped
@makeHtmlTagClass(tag="b", css_class="bold_css")
@makeHtmlTagClass(tag="i", css_class="italic_css")
def hello(name):
return "Hello, {}".format(name)
print(hello("Baby"))
#__call__方法会执行两次