Search code examples
pythondecoratorpython-decorators

Add method to decorator in Python


In this documentation about lru_cache I can see that there's the possibility to call a function on a decorator with the dot notation, for instance I can call:

lru_cache_decorated_func.cache_info()

What I'm trying to achieve is make my own decorator with my custom function to call that works and is called like cache_info().

So how I can add such a function to a decorator?


Solution

  • A decorator is nothing more (or less) than a callable returning a callable[0] aka

    @foo
    def bar():
       ...
    

    is exactly the same as:

    def bar():
        ...
    bar = foo(bar)
    

    There are various options to "smartify" decorators, what lru_cache does is pretty simple:

    • it wraps the decorated function in a wrapper function
    • it then sets to attributes on that wrapper function
    • and it returns the wrapper (swapping the original function for the wrapper)
    import functools
    
    def foo(fn):
        @functools.wraps(fn)
        def wrapper(*args, **kwargs):
            return fn(*args, **kwargs)
        wrapper.thing = 'yay'
        return wrapper
    
    @foo
    def bar(): ...
    
    print(bar.thing)
    

    will print yay.

    [0] or even a not-callable, as is the case for @property or @cached_property.