Demystifying Python Decorators: Build a Flask‑Style Router for Tornado

This tutorial explains how Python decorators work, demonstrates a simple decorator that adds database‑connection logic, shows how to return a wrapper function to avoid modifying existing calls, and walks through creating a Flask‑style @router decorator for Tornado web routing.

ITPUB
ITPUB
ITPUB
Demystifying Python Decorators: Build a Flask‑Style Router for Tornado

Python treats everything as an object, including functions, which allows them to be passed around and wrapped. The article starts with basic function examples to illustrate that a function can be passed as an argument and invoked inside another function.

Decorator Pattern in Python

The decorator pattern adds behavior before or after a target function runs. A classic example is wrapping database operations: a connect_db() call, the actual query, and a close_db() call.

def connect_db():
    print 'connect db'

def close_db():
    print 'close db'

def query_user():
    connect_db()
    print 'query the user'
    close_db()

query_user()  # connect db, query the user, close db

To avoid rewriting every call site, the article introduces a higher‑order function query_data that receives another function, wraps it with the connection logic, and returns the wrapper.

def query_data(query):
    def wrapper():
        connect_db()
        query()
        close_db()
    return wrapper

query_user = query_data(query_user)
query_user()  # executes the wrapped version without changing original code

Using the @ Syntax Sugar

Python’s @ decorator syntax is syntactic sugar for the same operation. The previous example can be written as:

def query_data(query):
    def wrapper():
        connect_db()
        query()
        close_db()
    return wrapper

@query_data
def query_user():
    print 'query some user'

query_user()  # equivalent to query_user = query_data(query_user)

Passing Arguments Through Decorators

When the wrapped function needs parameters, the wrapper can accept them and forward them to the original function.

def query_data(query):
    def wrapper(count):
        connect_db()
        query(count)
        close_db()
    return wrapper

@query_data
def query_user(count):
    print 'query some user limit  {count}'.format(count=count)

query_user(count=100)

Decorator with Parameters – Building a Router

Flask’s @app.route('/path') passes a URL pattern to the decorator. The article shows how to implement a similar @router decorator for Tornado.

def router(url):
    print 'router invoke url', url
    def query_data(query):
        print 'query_data invoke url', url
        def wrapper(count):
            connect_db()
            query(count)
            close_db()
        return wrapper
    return query_data

@router('/user')
def query_user(count):
    print 'query some user limit  {count}'.format(count=count)

query_user(count=100)

The call sequence works as follows: router('/user') returns query_data, which then decorates query_user. The final effect is equivalent to query_user = router('/user')(query_user).

By the end, readers understand how decorators can encapsulate cross‑cutting concerns such as database handling or routing, how the @ syntax simplifies their usage, and how to pass arguments both to the decorator and the wrapped function.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

tornadodecoratorsweb routingsyntactic sugar
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.