Merging Python decorators with arguments into a single one

  • A+
Category:Languages

I'm using two different decorators from two different libraries. Lets say: @decorator1(param1, param2) and @decorator2(param3, param4). That I often use in many functions as:

from moduleA import decorator1 from moduleB import decorator2  @decorator2(foo='param3', bar='param4') @decorator1(name='param1', state='param2') def myfunc(funcpar1, funcpar2):     ... 

Since it happens every time, I would like to create a custom decorator that handle both of them. Something like:

@mycustomdecorator(name='param1', state='param2',                    foo='param3', bar='param4') def myfunc(funcpar1, funcpar2):     ... 

How do I achieve that?

 


I would argue that you shouldn't - using the original names for the decorators gives much better readability.

However, if you really want to, you can do it like this:

import functools  from moduleA import decorator1 from moduleB import decorator2  def my_decorator(foo, bar, name, state):     def inner(func):         @decorator2(foo=foo, bar=bar)         @decorator1(name=name, state=state)         @functools.wraps(func)  # Not required, but generally considered good practice         def newfunc(*args, **kwargs)             return func(*args, **kwargs)         return newfunc     return inner  @my_decorator(foo='param3', bar='param4', name='param1', state='param2') def myfunc(funcpar1, funcpar2):     ... 

It's simple really - just write a decorator that returns another decorator which will have it's inner function decorated with the other two decorators ;)

It might also be a good idea to use functools.wraps, for the sake of good habits. It's standard library and helps a lot with debugging and interactive console use: https://docs.python.org/3.7/library/functools.html

In general though, I'd say the one extra line of code is more than worth the clarity of using the decorators separately. You'll thank yourself when you read your own code in 3 more months.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: