我如何在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 makebold(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
return "<b>" + fn(*args, **kwargs) + "</b>"
return wrapper
def makeitalic(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
return "<i>" + fn(*args, **kwargs) + "</i>"
return wrapper
@makebold
@makeitalic
def hello():
return "hello world"
@makebold
@makeitalic
def log(s):
return s
print hello() # returns "<b><i>hello world</i></b>"
print hello.__name__ # with functools.wraps() this returns "hello"
print log('hello') # returns "<b><i>hello</i></b>"
下面有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>
装饰器接受函数定义并创建一个新函数,该函数执行该函数并转换结果。
@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,它在内部执行函数并转换结果。
这个答案早就有了答案,但我想我会分享我的Decorator类,这使编写新的Decorator变得简单而紧凑。
from abc import ABCMeta, abstractclassmethod
class Decorator(metaclass=ABCMeta):
""" Acts as a base class for all decorators """
def __init__(self):
self.method = None
def __call__(self, method):
self.method = method
return self.call
@abstractclassmethod
def call(self, *args, **kwargs):
return self.method(*args, **kwargs)
首先,我认为这使装饰器的行为非常清晰,但也使定义新的装饰器变得非常简洁。对于上面列出的示例,您可以将其解为:
class MakeBold(Decorator):
def call():
return "<b>" + self.method() + "</b>"
class MakeItalic(Decorator):
def call():
return "<i>" + self.method() + "</i>"
@MakeBold()
@MakeItalic()
def say():
return "Hello"
您也可以使用它来执行更复杂的任务,例如,一个装饰器,它会自动将函数递归地应用于迭代器中的所有参数:
class ApplyRecursive(Decorator):
def __init__(self, *types):
super().__init__()
if not len(types):
types = (dict, list, tuple, set)
self._types = types
def call(self, arg):
if dict in self._types and isinstance(arg, dict):
return {key: self.call(value) for key, value in arg.items()}
if set in self._types and isinstance(arg, set):
return set(self.call(value) for value in arg)
if tuple in self._types and isinstance(arg, tuple):
return tuple(self.call(value) for value in arg)
if list in self._types and isinstance(arg, list):
return list(self.call(value) for value in arg)
return self.method(arg)
@ApplyRecursive(tuple, set, dict)
def double(arg):
return 2*arg
print(double(1))
print(double({'a': 1, 'b': 2}))
print(double({1, 2, 3}))
print(double((1, 2, 3, 4)))
print(double([1, 2, 3, 4, 5]))
哪些打印:
2
{'a': 2, 'b': 4}
{2, 4, 6}
(2, 4, 6, 8)
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
注意,这个示例没有在decorator的实例化中包含列表类型,因此在最终的print语句中,该方法应用于列表本身,而不是列表的元素。
装饰只是语法上的糖。
This
@decorator
def func():
...
扩展到
def func():
...
func = decorator(func)