如何创建函数装饰器并将它们链接在一起?

3146

我该如何在Python中创建两个装饰器以实现以下功能?

@make_bold
@make_italic
def say():
   return "Hello"

调用 say() 应该返回:

"<b><i>Hello</i></b>"

22个回答

0
Python 3.9中,lambda表达式可以用作装饰器。
关于您的问题,
@lambda func: (lambda *variable: '<b>' + func(*variable) + '</b>')
@lambda func: (lambda *variable: '<i>' + func(*variable) + '</i>')
def say():
    return "Hello"

print(say())

如果你想在第一次函数调用后重复使用上述的lambda函数,可以将它们赋值给一个变量并进行重用。以下是一个示例。
@make_bold := lambda func: (lambda *variable: '<b>' + func(*variable) + '</b>')
@make_italic := lambda func: (lambda *variable: '<i>' + func(*variable) + '</i>')
def say():
    return "Hello"

@make_bold
@make_italic
def say2():
    return "World"

print(say())
print(say2())

-1

问题

How do we make two decorators in Python that would do the following?

@make_bold
@make_italic
def say():
    return "Hello"

Calling say() should return "<b><i>Hello</i></b>"


解决方案


make_bold

from functools import update_wrapper  

class make_bold:

    def __new__(cls, kallable):
        instance = super().__new__(cls)
        instance = update_wrapper(instance, kallable)
        return instance

    def __init__(self, kallable):
        self._kallable = kallable
        self._file     = sys.stdout

    def __call__(self, *args, **kwargs):   
        # `iret` ...... initial return value
        # `oret` ...... output  return value
        iret = self._kallable(*args, **kwargs)
        oret = "<b>" + r + "</b>"
        
    def __getattr__(self, attrname:str):  
        return getattr(self._kallable, attrname) 

make_italic

from functools import update_wrapper  

class make_italic:

    def __new__(cls, kallable):
        instance = super().__new__(cls)
        instance = update_wrapper(instance, kallable)
        return instance

    def __init__(self, kallable):
        self._kallable = kallable
        self._file     = sys.stdout

    def __call__(self, *args, **kwargs):   
        # `iret` ...... initial return value
        # `oret` ...... output  return value
        iret = self._kallable(*args, **kwargs)
        ret  = "".join(str(x) for x in iret)
        oret = "<i>" + ret + "</i>"
        
    def __getattr__(self, attrname:str):  
        return getattr(self._kallable, attrname) 

我在make_italic函数中添加了一行额外的代码,用于修改被包装函数返回的值。
ret = "".join(str(x) for x in iret)

这行代码可能对某些人有用,也可能没有用。
   ABOUT...         ret = "".join(str(x) for x in iret)
     +--------------+---------------------------+----------+
     | non-standard |           input           |  output  |  
     | notation     |                           |          |
     | for          |                           |          |
     | input        |                           |          |
     | type         |                           |          |
     +--------------+---------------------------+----------+
     | string       | 'howdy'                   | 'howdy'  |
     | tuple<char>  | ('h', 'o', 'w', 'd', 'y') | 'howdy'  |
     | list<char>   | ['h', 'o', 'w', 'd', 'y'] | 'howdy'  |
     | list<string> | ['ho', 'wdy']             | 'howdy'  |
     | list<int>    | [1, 2, 3, 456]            | '123456' |
     +--------------+---------------------------+----------+

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接