简体   繁体   中英

How to pass a function's parameter variable to a decorator?

I'm basically trying to track events in an API. There are several routes with different functionalities. I came with something like this:

# defining a decorator like this:
class tracker():
    def __init__(self, data):
        self.data = data

    def __call__(self, function):
        @functools.wraps(function)
        async def decorated(*args, **kwargs):
            self.save_event(*args, **kwargs)
            return await function(*args, **kwargs)
        return decorated

    def save_event(self, *args, **kwargs):
        this_would_be_function_arg = self.data
        # do something with the data
        pass


# to be used like this:
@tracker(data=function_arg):
def my_func(function_arg):
    # something...
    pass

Is it possible? I know I could access from kwargs , but I won't always know whats being passed, and I don't need every single parameter, so I didn't want to get everything.

Function signatures from the inspect module can help.

With a saved signature of the wrapped function, you can bind the arguments to it at every call and look them up by name regardless of type (arg or kwarg).

Docs: introspecting callables

import inspect
import functools

class tracker():
    def __init__(self, data):
        self.data = data
        self.signature = None

    def __call__(self, function):
        self.signature = inspect.signature(function)
        @functools.wraps(function)
        def decorated(*args, **kwargs):
            bound = self.signature.bind(*args, **kwargs)
            bound.apply_defaults()
            self.save_event(bound.arguments[self.data])
            return function(*args, **kwargs)
        return decorated

    def save_event(self, value):
        print(f"called with {self.data}={value}")

@tracker(data='function_arg')
def my_func(arg1, function_arg=None):
    pass

my_func(0,10)
my_func(10, function_arg=20)
my_func(-1)

# output:
# called with function_arg=10
# called with function_arg=20
# called with function_arg=None

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM