Using decorators with argument in Python

Duncan Booth duncan.booth at invalid.invalid
Thu Jun 30 05:00:30 EDT 2011


Lie Ryan <lie.1296 at gmail.com> wrote:

> Simplicity is one, using @decor() means you have at least three-level
> nested functions, which means the code is likely to be very huge and
> perhaps unnecessarily.
> 

If you don't like the extra level of function nesting that you get from 
returning a decorator factory instead of a decorator then you can factor 
out the complexity by using a decorator.

---------------------------------------------
from functools import wraps

def decorator_with_args(deco):
    """Wrap a decorator so that it can take arguments"""
    @wraps(deco)
    def wrapper(*args, **kw):
        @wraps(deco)
        def inner(f):
            return deco(f, *args, **kw)
        return inner
    return wrapper

@decorator_with_args
def repeat(f, count=2):
    """Decorator which calls the decorated function <count> times"""
    @wraps(f)
    def wrapper(*args, **kw):
        return [f(*args, **kw) for i in range(count)]
    return wrapper

@repeat(3)
def ticker(msg):
    print("tick", msg)

ticker("tock")
-----------------------------------------
decorator_with_args is a decorator factory that creates a decorator 
factory from a decorator and passes its arguments through to the 
underlying decorator.

-- 
Duncan Booth http://kupuguy.blogspot.com



More information about the Python-list mailing list