Search code examples
pythondecoratorpython-decorators

What is the intended lifetime of a Python decorator?


My question revolves around the intended lifetime of an implemented Python decorator. From realpython.org it says:

''By definition, a decorator is a function that takes another function and extends the behavior of the latter function without explicitly modifying it.''

To me, it seems like decorators quite frequently are used in examples online to temporarily modify or extend a python function, such as in the html formatting examples.

Example:

Let's say that I work at a web development company and at the top of all of my webpages I call this Python function page_welcome().

def page_welcome():
    return "Welcome to XYZ's company webpage!"

Now, some developer joins the company and decides we should make this stand out more by modifying the function with some bold and italics.

def makebold(fn):
    def wrapped():
        return "<b>" + fn() + "</b>"
    return wrapped    

def makeitalic(fn):
    def wrapped():
        return "<i>" + fn() + "</i>"
    return wrapped    

@makebold
@makeitalic
def page_welcome():
    return "Welcome to XYZ's company webpage!"

If we decide this change is to be permanent, are decorators the best way of leaving in this permanent modification?

Note: The example above is the decorator example from this link (modified slightly): How to make a chain of function decorators?


Solution

  • Decorators' main purpose is not for temporary modification of function behaviour. The word "temporarily" is odd here. It is better to think about them as decomposition of responsibilities and code reuse. They are mostly used to add some behaviour which is not uniquely bound to decorating function and can be used for other functions too. One good example is the @memoized decorator, which remembers the value computed by the decorated function (which may take a lot of time to compute) and next time returns the value immediately. Such a decorator can be reused many times and, besides that, it makes core much more readable: instead of bloating your function with memoization code you add a single line which clearly states what actually happens.