How to avoid "()" when writing a decorator accepting optional arguments?

Terry Reedy tjreedy at udel.edu
Sat Jun 11 16:36:25 EDT 2011


On 6/11/2011 3:27 PM, Giampaolo Rodolà wrote:
> I've written this decorator to deprecate a function and (optionally)
> provide a callable as replacement
>
>       def deprecated(repfun=None):
>          """A decorator which can be used to mark functions as deprecated.
>          Optional repfun is a callable that will be called with the same args
>          as the decorated function.
>          """
>          def outer(fun):
>              def inner(*args, **kwargs):
>                  msg = "%s is deprecated" % fun.__name__
>                  if repfun is not None:
>                      msg += "; use %s instead" % (repfun.__name__)
>                  warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
>                  if repfun is not None:
>                      return repfun(*args, **kwargs)
>                  else:
>                      return fun(*args, **kwargs)
>              return inner
>          return outer
>
>
> Now, I can use my decorator as such:
>
>      @deprecated()
>      def foo():
>          return 0
>
> ...or provide an optional argument:
>
>      @deprecated(some_function)
>      def foo():
>          return 0
>
> ...but I don't know how to modify it so that I can omit parentheses:
>
>      @deprecated
>      def foo():
>          return 0

These are fundamentally different beasts. One makes a call to create the 
decorator. The other is the decorator. Write two decorators.
The unparameterized version is trivial.

def outer(fun):
     def inner(*args, **kwargs):
         msg = "%s is deprecated" % fun.__name__
         warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
         return fun(*args, **kwargs)
     rturn inner

The parameterized version will be simpler also (with None possibility
deleted).

-- 
Terry Jan Reedy





More information about the Python-list mailing list