Why can't Python decorators be chained across definitions?

前端 未结 3 1904
没有蜡笔的小新
没有蜡笔的小新 2021-02-09 01:43

Why arn\'t the following two scripts equivalent?

(Taken from another question: Understanding Python Decorators)

def makebold(fn):
    def wrapped():
             


        
3条回答
  •  耶瑟儿~
    2021-02-09 02:02

    The reason is because wrapped() inside of makebold doesn't accept any arguments.

    When you use the decorator like that it can cause some issues, I'll post an example of how to achieve what you're wanting though, give me just a moment.

    Here is a working example of what you need.

    def makebold(rewrap=False):
        if rewrap:
            def inner(decorator):
                def rewrapper(func):
                    def wrapped(*args, **kwargs):
                        return "%s" % decorator(func)(*args,**kwargs)
                    return wrapped
                return rewrapper
            return inner
    
        else:
            def inner(func):
                def wrapped(*args, **kwargs):
                    return "%s" % func(*args, **kwargs)    
                return wrapped
            return inner
    
    @makebold(rewrap=True)
    def makeitalic(fn):
        def wrapped(*args, **kwargs):
            return "%s" % fn(*args, **kwargs)
        return wrapped
    
    @makeitalic
    def hello():
        return "hello world"
    
    @makebold()
    def hello2():
        return "Bob Dole"    
    
    if __name__ == "__main__":
        print hello()   
        print hello2()
    

    makebold is kinda ugly, but it shows you how to write a decorator that can optionally wrap another decorator.

    Here is the output from the above script:

    hello world
    Bob Dole
    

    Note that makebold is the only recursive decorator. Also note the subtle difference in usage: @makebold() vs @makeitalic.

提交回复
热议问题