Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to strip decorators from a function in Python

Let's say I have the following:

def with_connection(f):     def decorated(*args, **kwargs):         f(get_connection(...), *args, **kwargs)     return decorated  @with_connection def spam(connection):     # Do something 

I want to test the spam function without going through the hassle of setting up a connection (or whatever the decorator is doing).

Given spam, how do I strip the decorator from it and get the underlying "undecorated" function?

like image 676
Herge Avatar asked Jul 22 '09 15:07

Herge


People also ask

Are decorators Pythonic?

Decorators are a very powerful and useful tool in Python since it allows programmers to modify the behaviour of a function or class. Decorators allow us to wrap another function in order to extend the behaviour of the wrapped function, without permanently modifying it.

Is Python decorator a closure?

Decorators return a closure. A closure is what is returned by a decorator. The second function shown in this gist is say_hello . This function prints a string and returns 'None'.

Why decorators in Python are pure genius?

Decorators are a prime-time example of a perfectly implemented feature. It does take a while to wrap your head around, but it's worth it. As you start using them, you'll notice how they don't overcomplicate things and make your code neat and snazzy.

What are fancy decorators in Python?

Decorator in Python is an important feature used to add functionalities to an existing function, object, or code without modifying its structure permanently. It allows you to wrap a function to another function and extend its behavior.


1 Answers

There's been a bit of an update for this question. If you're using Python 3, you can use __wrapped__ property for decorators from stdlib.

Here's an example from Python Cookbook, 3rd edition, section 9.3 Unwrapping decorators

>>> @somedecorator >>> def add(x, y): ...     return x + y ... >>> orig_add = add.__wrapped__ >>> orig_add(3, 4) 7 >>> 

If you are trying to unwrap a function from custom decorator, the decorator function needs to use wraps function from functools See discussion in Python Cookbook, 3rd edition, section 9.2 Preserving function metadata when writing decorators

>>> from functools import wraps >>> def somedecorator(func): ...    @wraps(func) ...    def wrapper(*args, **kwargs): ...       # decorator implementation here ...       # ...... ...       return func(*args, **kwargs) ... ...    return wrapper 
like image 98
Alex Volkov Avatar answered Sep 21 '22 14:09

Alex Volkov