简体   繁体   中英

Optional argument decorator

Can you explain to me how the partial function is working here?

def debug(func=None, *, prefix=''):
    if func is None:
        return partial(debug, prefix=prefix)
    msg = prefix + func.__name__
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(msg)
        return func(*args, **kwargs)
    return wrapper

The debug function is designed so that it can optionally be called with the prefix keyword-only argument if you want, when you apply it as a decorator:

@debug(prefix="foo"):  # calling debug with a prefix works
def foo():
    pass

@debug                 # skipping the call also works
def bar():
    pass

The way it does this is by using functools.partial . The partial function returns a callable argument that behaves just like the function you pass it, but it will add in the extra arguments you pass to partial whenever the partial objects gets called itself.

Here's an example:

from functools import partial

def foo(arg1, arg2):
    print(arg1, arg2)

foo("hi", "there") # prints "hi there"

bar = partial(foo, "bar")
bar("quux") # prints "bar quux"

baz = partial(foo, arg2="baz")
baz("hmm") # prints "hmm baz"

The decorator syntax using @decorator passes the function that is defined on the next line as a single argument to the decorator. But if you call something on the decorator line, the function gets passed to the return value of the call instead. So:

@debug
def foo():
    pass

Is equivalent to:

def foo():
    pass

foo = debug(foo)

Whereas:

@debug(prefix="foo")
def foo():
    pass

Is equivalent to:

deco = debug(prefix="foo") # this is partial(debug, prefix="foo")

@deco
def foo():
    pass

Which thanks to partial is equivalent to:

def foo():
    pass

foo = debug(foo, prefix="foo")  # passing both arguments here, that's not normally possible!

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