How to create a Python decorator that can be used either with or without parameters?

前端 未结 13 1616
死守一世寂寞
死守一世寂寞 2020-11-30 21:26

I\'d like to create a Python decorator that can be used either with parameters:

@redirect_output(\"somewhere.log\")
def foo():
    ....

or

13条回答
  •  一整个雨季
    2020-11-30 21:46

    Several answers here already address your problem nicely. With respect to style, however, I prefer solving this decorator predicament using functools.partial, as suggested in David Beazley's Python Cookbook 3:

    from functools import partial, wraps
    
    def decorator(func=None, foo='spam'):
        if func is None:
             return partial(decorator, foo=foo)
    
        @wraps(func)
        def wrapper(*args, **kwargs):
            # do something with `func` and `foo`, if you're so inclined
            pass
    
        return wrapper
    

    While yes, you can just do

    @decorator()
    def f(*args, **kwargs):
        pass
    

    without funky workarounds, I find it strange looking, and I like having the option of simply decorating with @decorator.

    As for the secondary mission objective, redirecting a function's output is addressed in this Stack Overflow post.


    If you want to dive deeper, check out Chapter 9 (Metaprogramming) in Python Cookbook 3, which is freely available to be read online.

    Some of that material is live demoed (plus more!) in Beazley's awesome YouTube video Python 3 Metaprogramming.

    Happy coding :)

提交回复
热议问题