Leagsaidh Gordon
Leagsaidh Gordon

Reputation: 1701

Python wrap function with unknown arguments

If I have this function:

def foo(arg_one, arg_two):
    pass

I can wrap it like so:

def bar(arg_one, arg_two):
    return foo(arg_one, arg_two)

foo = bar

Is it possible to do this without knowing foo's required arguments, and if so, how?

Upvotes: 3

Views: 718

Answers (4)

smarie
smarie

Reputation: 5156

In addition to alecxe's answer, if you wish your wrapper to preserve the signature (in other words to appear to its users as if it were the wrapped function), you may wish to have a look at functools.wraps and its replacement makefun.wraps, that fixes a few shortcomings and extends its usage to cases where you would like to modify the signature. See here for a short explanation of the difference. I am the author of makefun by the way ;)

This is how you would code it:

from makefun import wraps

@wraps(foo)
def bar(*args, **kwargs):
    return foo(*args, **kwargs)

Upvotes: 0

Yauhen Yakimovich
Yauhen Yakimovich

Reputation: 14211

Here is another slightly general use case (in addition to answer by Blender):

Typically in OOP when extending objects, one actually needs to override a method and (carefully) extend or even change the signature (order and number of arguments of the extended method), e.g. in __init__() methods which are object constructors.

Here is an example how to apply *args, **kwds for this purpose:

class Foo(object):
    def __init(self, foo_positional_arg, foo_optional_arg=None):
        pass


class Bar(Foo):

    def __init__(self, bar_postional_arg, bar_optional_arg=None, *args, **kwds):
        self.bar_postional_arg = bar_postional_arg
        self.bar_optional_arg = bar_optional_arg
        super(Bar, self).__init__(*args, **kwds)

In fact one can actually indeed change the order of the signature or trap the arguments from the previous (wrapped) full or partial signature.

def __init__(self, bar_postional_arg, foo_positional, foo_optional_arg=False, bar_optional_arg=None, *args, **kwds):

This proves again how extremely flexible(!) is the *args, **kwds mechanism in python functions (and methods).

Upvotes: 2

alecxe
alecxe

Reputation: 473833

You can use *args and **kwargs:

def bar(*args, **kwargs):
    return foo(*args, **kwargs)

args is a list of positional arguments.

kwargs is a dictionary of keyword arguments.

Note that calling those variables args and kwargs is just a naming convention. * and ** do all the magic for unpacking the arguments.

Also see:

Upvotes: 4

Blender
Blender

Reputation: 298136

You can use the argument unpacking operators (or whatever they're called):

def bar(*args, **kwargs):
    return foo(*args, **kwargs)

If you don't plan on passing any keyword arguments, you can remove **kwargs.

Upvotes: 5

Related Questions