Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use the python-decorator package to decorate classmethods?

I'm have a decorator that I want to use to decorate class methods. In the following example, the @mydec decorator works fine on its own, however it does not preserve the function signature when using help() or pydoc. In order to fix this, I looked at using @decorator python-decorator package:

import functools
import decorator


@decorator.decorator
def mydec(func):
    @functools.wraps(func)
    def inner(cls, *args, **kwargs):
        # do some stuff
        return func(cls, *args, **kwargs)
    return inner


class Foo(object):
    @classmethod
    @mydec
    def bar(cls, baz='test', qux=None):
        print (baz, qux)


Foo.bar()

Unfortunately, this results in the following exception:

Traceback (most recent call last):
  File "/tmp/test.py", line 21, in <module>
    Foo.bar()
  File "<string>", line 2, in bar
TypeError: mydec() takes exactly 1 argument (4 given)
like image 867
Ben Davis Avatar asked Sep 02 '13 16:09

Ben Davis


People also ask

How do you decorate a class in Python?

To decorate a method in a class, first use the '@' symbol followed by the name of the decorator function. A decorator is simply a function that takes a function as an argument and returns yet another function. Here, when we decorate, multiply_together with integer_check, the integer function gets called.

Can you decorate a variable in Python?

No, decorator syntax is only valid on functions and classes. Decorators exist because you can't just wrap a function or class declaration in a function call; simple variables you can.

Which symbol can be used to decorate a function in Python?

Decorators. The main use case of the symbol @ in Python are decorators. In Python, a decorator extends the functionality of an existing function or class.

How do decorators work in flask?

Understanding Flask decoratorsA decorator is a function that takes in another function as a parameter and then returns a function. This is possible because Python gives functions special status. A function can be used as a parameter and a return value, while also being assigned to a variable.


1 Answers

You do not need to provide your own wrapper anymore, just use @decorator.decorator on the inner function, which takes one extra first positional argument, the function wrapped:

@decorator.decorator
def mydec(func, cls, *args, **kwargs):
    # do some stuff
    return func(cls, *args, **kwargs)

The decorator package doesn't use a closure for decorators and instead passes in the wrapped function as an argument.

Demo:

>>> @decorator.decorator
... def mydec(func, cls, *args, **kwargs):
...     # do some stuff
...     return func(cls, *args, **kwargs)
... 
>>> class Foo(object):
...     @classmethod
...     @mydec
...     def bar(cls, baz='test', qux=None):
...         print (baz, qux)
... 
>>> Foo.bar()
('test', None)
like image 105
Martijn Pieters Avatar answered Oct 31 '22 18:10

Martijn Pieters