RattleyCooper
RattleyCooper

Reputation: 5207

Decorated function along with original, without having to re-write the function

If I have a decorator and a function, but I would like to use the decorated function along with the undecorated version of that function, what would I do?

I haven't used decorators much and from what I can find, it seems as if you would have to write out 2 separate functions to accomplish this, or call the decorator with the function as the parameter which can be somewhat confusing when dealing with multiple decorators.

To work around this, I am writing out a function, then I use a somewhat roundabout way of decorating the function and returning that decorated function after the fact. So I have access to both the undecorated and the decorated versions of that function. From what I can tell, the method in which this is accomplished is looked down upon a little bit, but it has been working for me so far. I cannot imagine that this is the best way to go about this.

Essentially, I pass the function I want to decorate, along with the decorator functions, to a method that inspects the functions text, adds the @decorator syntax to the text, then it adds the decorator functions into the __builtins__ module temporarily so I can exec the text into a dictionary to define the new decorated function. This new function object is extracted from the dictionary and is returned as the new decorated function.

I'm pretty sure this is not the best way to go about this. I don't imagine it would work in all situations, but I also don't want to have to call the decorated functions or rewrite the function every time.

Upvotes: 2

Views: 903

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1123400

Don't use the decorator as a decorator then. Remember, a decorator is syntactic sugar, but you don't have to use it.

The syntax:

@decorator_expr
def decorated_func():
    pass

is really executed as:

def decorated_func():
    pass
decorated_func = decorator_expr(decorated_func)

To keep the 'original' and a decorated version, then, just assign the output of the decorator to a different name:

def foo():
    pass

foo_decorated = decorator_expr(foo)

Alternatively, use the decorator callable every time you need a decorated version:

result = decorator_expr(foo)()

Upvotes: 6

Related Questions