4

I have created many functions that are divided into different files, now I would like to apply the same decorator for all of them without modifying the files and without applying the decorators one by one.

I have tried to use this explanation written by delnan, but I got no success for imported functions.

About the decorator, it must update a list every time a function within a class is executexecuted with the function arguments and values, just like this other question I asked.

Any suggestions to help me with this issue? Thanks

Community
  • 1
  • 1

1 Answers1

10

A little bit of introspection (dir()) and dynamic look-up with getattr() and setattr().

First we iterate over all names found in module and check for objects that look like functions. After that we simply reassign old function with decorated one.

main.py:

import types
import functools

def decorate_all_in_module(module, decorator):
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, types.FunctionType):
            setattr(module, name, decorator(obj))

def my_decorator(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        print(f)
        return f(*args, **kwargs)
    return wrapper

import mymod1
decorate_all_in_module(mymod1, decorator)

mymod1.py:

def f(x):
    print(x)


def g(x, y):
    print(x + y)

Output:

<function f at 0x101e309d8>
2
<function g at 0x101e30a60>
7

Process does not goes that smooth if you use star imports (from mymod import *). Reason is simple - because all names are in one huge bag and there no differentiation on where they come from, you need a lot of additional tricks to find what exactly you want to patch. But, well, that's why we use namespaces - because they are one honking great idea.

Łukasz Rogalski
  • 22,092
  • 8
  • 59
  • 93
  • Thank you for your help, it worked fine. In fact, I asked this question to complete [another question](http://stackoverflow.com/questions/39154006/update-a-list-every-time-a-function-within-a-class-is-executexecuted-with-the-fu) I had asked. I thought I could solve my problem from this, but it was not the case. I would like my decorator to save the args and function name every time some function from the imported class is ran. Could you help me with this new subject? – Jônathan Dambros Aug 29 '16 at 11:56
  • You want do decorate all methods of class? Process is fairly similar, you do `dir(class)` and look for methods and not functions. I'm quite sure you can figure that out yourself based on template above. – Łukasz Rogalski Aug 29 '16 at 12:12
  • Ok, thank you so much. I have used python as a free tool to replace Matlab, until now I have used it only as a numerical tool. I see I still have a lot to learn, but nothing to take away my will to learn it. Again, thank you. – Jônathan Dambros Aug 29 '16 at 12:26