简体   繁体   中英

How can I extend a library's decorator?

I would like to extend a library's decorator. I know that I can just call both decorators:

@my_decorator
@lib_decorator
def func():
    pass

But I would like to avoid having to pass @lib_decorator to each function each time. I would like my decorator to automatically decorate func() with lib_decorator . How can I do this? Can they be nested?

You can incorporate the lib's decorator within yours. For simple, argument-less decorators, it's rather straight-forward:

def my_decorator():
    @lib_decorator  # <--- Just include the lib's decorator here
    def inner:
        func(*args, **kwargs)
    return inner

It's a bit trickier for decorators that have arguments. Just remember that your decorator is replacing the decorated function with the inner-most function. So that's the one you need to decorate. So if you call your decorator with args, eg

@my_decorator(arg)
def func():
    pass

Then decorate the inner function with the lib decorator:

def my_decorator(arg):
    def wrapper(func):

        @lib_decorator  # <--- Just include the lib's decorator here
        def inner(*args, **kwargs):
            func(*args, **kwargs)

        return inner

    return wrapper

Or, using the class form of the decorator function:

class my_decorator():
    def __init__(self, arg):
        pass

    def __call__(self, func):
        @lib_decorator  # <--- Just include the lib's decorator here
        def inner(*args, **kwargs):
            func(*args, **kwargs)

        return inner

You can easily transform a decoration like yours:

@my_decorator
@lib_decorator
def func():
    pass

To this simpler decoration, using function composition:

my_composed_decorator = lambda func: my_decorator(lib_decorator(func))

@my_composed_decorator
def func():
    pass

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