Defining Python decorators for a complete module

前端 未结 2 782
抹茶落季
抹茶落季 2020-12-09 18:06

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 @dec

相关标签:
2条回答
  • 2020-12-09 18:40

    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:

    1. No need to modify the third-party source file
    2. It is clear from the call site that I should go look at my_wrapper_module to see what I'm calling, and that I'm not using the undecorated versions of the functions
    3. It is clear from my_wrapper_module what functions are being exported, that they originally come from some_module, and that they all have the same decorator applied
    4. Any code that imports some_module directly isn't silently and inexplicably affected; this could be particularly important if the third-party code is more than one module

    But 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.

    0 讨论(0)
  • 2020-12-09 18:44

    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)
    
    0 讨论(0)
提交回复
热议问题