Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I programmatically change the argspec of a function in a python decorator?

Given a function:

def func(f1, kw='default'):
    pass
bare_argspec = inspect.getargspec(func)

@decorator
def func2(f1, kw='default'):
    pass
decorated_argspec = inspect.getargspec(func2)

How can I create a decorator such that bare_argspec == decorated_argspec?

(As to why, the framework that calls the decorated function does argspec inspection to choose what to pass in, so the decorator has to retain the same argspec in order to play nice. When I posed this question on #python, I got a long speech about why the framework sucks, which is not what I'm looking for; I have to solve the problem here. Also, I'm just interested in the answer, too)

like image 941
Chris R Avatar asked Sep 16 '10 17:09

Chris R


People also ask

Can Python decorators take arguments?

The decorator arguments are accessible to the inner decorator through a closure, exactly like how the wrapped() inner function can access f . And since closures extend to all the levels of inner functions, arg is also accessible from within wrapped() if necessary.

Which keyword is used for decorating a function in Python?

Defining the General Purpose Decorators in Python If you noticed, we used *args and **kwargs in the previous example. These variables help define general-purpose decorators in Python. They will collect all the positional and keyword arguments that you pass, and store them in the args and kwargs variables, respectively.

Can decorator return value Python?

Python Decorators 101 Return values from decorated functions don't get returned by default unless the decorator allows it. In this lesson, you'll see how to get return values out of decorated functions by making a small change to the decorator.

Are decorators Pythonic?

Recall that a decorator is just a regular Python function. All the usual tools for easy reusability are available. Let's move the decorator to its own module that can be used in many other functions. Note: You can name your inner function whatever you want, and a generic name like wrapper() is usually okay.


1 Answers

Michele Simionato's decorator module has a decorator called decorator which preserves function argspecs.

import inspect
import decorator

def func(f1, kw='default'):
    pass
bare_argspec = inspect.getargspec(func)
print(bare_argspec)
# ArgSpec(args=['f1', 'kw'], varargs=None, keywords=None, defaults=('default',))

@decorator.decorator
def mydecorator(func,*args,**kw):
    result=func(*args,**kw)
    return result

@mydecorator
def func2(f1, kw='default'):
    pass
decorated_argspec = inspect.getargspec(func2)
print(decorated_argspec)
# ArgSpec(args=['f1', 'kw'], varargs=None, keywords=None, defaults=('default',))

assert(bare_argspec==decorated_argspec)
like image 106
unutbu Avatar answered Oct 24 '22 03:10

unutbu