我如何在Python中制作两个装饰器来完成以下操作?
@make_bold
@make_italic
def say():
return "Hello"
调用say()应返回:
"<b><i>Hello</i></b>"
我如何在Python中制作两个装饰器来完成以下操作?
@make_bold
@make_italic
def say():
return "Hello"
调用say()应返回:
"<b><i>Hello</i></b>"
当前回答
装饰器接受函数定义并创建一个新函数,该函数执行该函数并转换结果。
@deco
def do():
...
相当于:
do = deco(do)
例子:
def deco(func):
def inner(letter):
return func(letter).upper() #upper
return inner
This
@deco
def do(number):
return chr(number) # number to letter
相当于这个
def do2(number):
return chr(number)
do2 = deco(do2)
65<=>“a”
print(do(65))
print(do2(65))
>>> B
>>> B
要理解decorator,需要注意的是,decorator创建了一个新的函数do,它在内部执行函数并转换结果。
其他回答
或者,您可以编写一个工厂函数,该函数返回一个装饰器,该装饰器将装饰函数的返回值包装在传递给工厂函数的标记中。例如:
from functools import wraps
def wrap_in_tag(tag):
def factory(func):
@wraps(func)
def decorator():
return '<%(tag)s>%(rv)s</%(tag)s>' % (
{'tag': tag, 'rv': func()})
return decorator
return factory
这使您能够编写:
@wrap_in_tag('b')
@wrap_in_tag('i')
def say():
return 'hello'
or
makebold = wrap_in_tag('b')
makeitalic = wrap_in_tag('i')
@makebold
@makeitalic
def say():
return 'hello'
就我个人而言,我会用不同的方式来编写装饰器:
from functools import wraps
def wrap_in_tag(tag):
def factory(func):
@wraps(func)
def decorator(val):
return func('<%(tag)s>%(val)s</%(tag)s>' %
{'tag': tag, 'val': val})
return decorator
return factory
这将产生:
@wrap_in_tag('b')
@wrap_in_tag('i')
def say(val):
return val
say('hello')
不要忘了decorator语法是一种简写的构造:
say = wrap_in_tag('b')(wrap_in_tag('i')(say)))
做同样事情的另一种方式:
class bol(object):
def __init__(self, f):
self.f = f
def __call__(self):
return "<b>{}</b>".format(self.f())
class ita(object):
def __init__(self, f):
self.f = f
def __call__(self):
return "<i>{}</i>".format(self.f())
@bol
@ita
def sayhi():
return 'hi'
或者,更灵活地说:
class sty(object):
def __init__(self, tag):
self.tag = tag
def __call__(self, f):
def newf():
return "<{tag}>{res}</{tag}>".format(res=f(), tag=self.tag)
return newf
@sty('b')
@sty('i')
def sayhi():
return 'hi'
下面有make_bold()和make_italic():
def make_bold(func):
def core(*args, **kwargs):
result = func(*args, **kwargs)
return "<b>" + result + "</b>"
return core
def make_italic(func):
def core(*args, **kwargs):
result = func(*args, **kwargs)
return "<i>" + result + "</i>"
return core
您可以使用say()将它们用作装饰器,如下所示:
@make_bold
@make_italic
def say():
return "Hello"
print(say())
输出:
<b><i>Hello</i></b>
当然,您可以直接使用make_bold()和make_italic()而不使用修饰符,如下所示:
def say():
return "Hello"
f1 = make_italic(say)
f2 = make_bold(f1)
result = f2()
print(result)
简而言之:
def say():
return "Hello"
result = make_bold(make_italic(say))()
print(result)
输出:
<b><i>Hello</i></b>
Python装饰器为另一个函数添加了额外的功能
斜体装饰符可以如下所示
def makeitalic(fn):
def newFunc():
return "<i>" + fn() + "</i>"
return newFunc
注意,函数是在函数内部定义的。它基本上是用新定义的函数替换函数。例如,我有这门课
class foo:
def bar(self):
print "hi"
def foobar(self):
print "hi again"
现在,我希望两个函数在完成后和完成前都打印“---”。我可以在每个打印语句前后添加一个打印“---”。但因为我不喜欢重复自己,我会做一个装饰师
def addDashes(fn): # notice it takes a function as an argument
def newFunction(self): # define a new function
print "---"
fn(self) # call the original function
print "---"
return newFunction
# Return the newly defined function - it will "replace" the original
所以现在我可以把我的班级改成
class foo:
@addDashes
def bar(self):
print "hi"
@addDashes
def foobar(self):
print "hi again"
有关装饰器的详细信息,请查看http://www.ibm.com/developerworks/linux/library/l-cpdecor.html
装饰只是语法上的糖。
This
@decorator
def func():
...
扩展到
def func():
...
func = decorator(func)