Reputation: 1836
I have a module which contains a lot of functions (more than 25). I want to add a common decorator function to each of these functions. The normal way to do is to add a @decorator line above each function, but I was wondering if there is a better way to do it? Probably I can declare a global decorator at the top of the module or something else?
Note that since I am using someone else's code, I want to minimize the number of lines changed, so modifying the module is not ideal for me.
Thanks.
Upvotes: 17
Views: 6767
Reputation: 71545
I think applying a decorator en-masse such that it's not obvious where you will go looking to find out about the function (at its definition) is generally a bad idea. Explicit is better than implicit, and all that.
If you want to apply the decorator to some third party module's functions, without modifying the third-party code, here is how I would do it:
# my_wrapper_module.py
import some_module
import functools
def some_decorator(func):
@functools.wraps(func):
def wrapper(*args, **kwargs):
...
return wrapper
FUNCTION_NAMES = [
'some_func_1',
'some_func_2',
'some_func_3',
...
]
for name in FUNCTION_NAMES:
globals()[name] = some_decorator(getattr(some_module, name))
And then use these functions elsewhere by doing from my_wrapper_module import some_func_2
, etc.
For me, this has the following advantages:
my_wrapper_module
to see what I'm calling, and that I'm not using the undecorated versions of the functionsmy_wrapper_module
what functions are being exported, that they originally come from some_module
, and that they all have the same decorator appliedsome_module
directly isn't silently and inexplicably affected; this could be particularly important if the third-party code is more than one moduleBut if what you're trying to do is hack a third-party library so that internal calls are affected, then this is not what you want.
Upvotes: 10
Reputation: 304393
If your decorator is called my_decorator
### Decorate all the above functions
import types
for k,v in globals().items():
if isinstance(v, types.FunctionType):
globals()[k] = my_decorator(v)
You could also apply this to the module after importing it
import othermodule
import types
for k,v in vars(othermodule).items():
if isinstance(v, types.FunctionType):
vars(othermodule)[k] = my_decorator(v)
Upvotes: 20