I am trying to figure out how to get the names of all decorators on a method. I can already get the method name and docstring, but cannot figure out how to get a list of decorators.
Decorators can be implemented in a number of different ways. One useful use-case for decorators involves using them with methods defined in a class. Decorating methods in the classes we create can extend the functionality of the defined method.
A decorator is a design pattern in Python that allows a user to add new functionality to an existing object without modifying its structure. Decorators are usually called before the definition of a function you want to decorate.
Decorators use a special syntax in JavaScript, whereby they are prefixed with an @ symbol and placed immediately before the code being decorated.
When we mention the word "decorator", what enters your mind? Well, likely something that adds beauty to an existing object. An example is when we hang a picture frame to a wall to enhance the room. Decorators in Python add some feature or functionality to an existing function without altering it.
I'm surprised that this question is so old and no one has taken the time to add the actual introspective way to do this, so here it is:
The code you want to inspect...
def template(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper baz = template che = template class Foo(object): @baz @che def bar(self): pass
Now you can inspect the above Foo
class with something like this...
import ast import inspect def get_decorators(cls): target = cls decorators = {} def visit_FunctionDef(node): decorators[node.name] = [] for n in node.decorator_list: name = '' if isinstance(n, ast.Call): name = n.func.attr if isinstance(n.func, ast.Attribute) else n.func.id else: name = n.attr if isinstance(n, ast.Attribute) else n.id decorators[node.name].append(name) node_iter = ast.NodeVisitor() node_iter.visit_FunctionDef = visit_FunctionDef node_iter.visit(ast.parse(inspect.getsource(target))) return decorators print get_decorators(Foo)
That should print something like this...
{'bar': ['baz', 'che']}
or at least it did when I tested this with Python 2.7.9 real quick :)
If you can change the way you call the decorators from
class Foo(object): @many @decorators @here def bar(self): pass
to
class Foo(object): @register(many,decos,here) def bar(self): pass
then you could register the decorators this way:
def register(*decorators): def register_wrapper(func): for deco in decorators[::-1]: func=deco(func) func._decorators=decorators return func return register_wrapper
For example:
def many(f): def wrapper(*args,**kwds): return f(*args,**kwds) return wrapper decos = here = many class Foo(object): @register(many,decos,here) def bar(self): pass foo=Foo()
Here we access the tuple of decorators:
print(foo.bar._decorators) # (<function many at 0xb76d9d14>, <function decos at 0xb76d9d4c>, <function here at 0xb76d9d84>)
Here we print just the names of the decorators:
print([d.func_name for d in foo.bar._decorators]) # ['many', 'decos', 'here']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With