dchoruzy
dchoruzy

Reputation: 349

Pass all arguments from one function to another

I'm creating wrapper librabry for some external API. I have a method which takes about 20 arguments.

so my function looks like:

def create_project(
            self,
            client_id: int,
            name: str,
            is_billable: bool,
            bill_by: str,
            budget_by: str,
            code: Optional[str] = None,
            is_active: Optional[bool] = None,
            ...

and inside this function I would like to request external api like this:

requests.post(url, headers=self.headers, data=data)

where data would be dictionary created from all arguments passed in this function. I could just define function like this create_post(self, **kwargs) but we wouldnt know which arguments are required without checking the documentation.

Upvotes: 1

Views: 1130

Answers (1)

Pierre D
Pierre D

Reputation: 26211

One construct I use from time to time is, as the first line of a function:

def create_project(self, client_id: int, ...):
    allargs = locals()

allargs contains just the variables that were local on that first line, i.e. the function arguments.

You could then do something along the lines of:

    # example: exclude self, and any other args that you
    # don't want to expose to request.post()

    exclude = {'self', 'super_secret', ...}
    data = {k: v for k, v in allargs.items() if k not in exclude}
    request.post(url, headers=self.headers, data=data)

Or whatever suits your needs. Be aware of mutable variables if there are any; no deep copy is done in the above.

Two other ways I use this are:

  1. For variable inspection in an interactive environment (e.g., Jupyter notebook), without resorting to the debugger:

        # some place of interest inside the function:
        global foo
        foo = locals()
    

    and, in another cell, after having called the function:

    locals().update({k:v for k, v in foo.items() if k in 'var0 var1 var2'.split()})
    

    That "brings in" the current context some of the variables of interest. I can then inspect var0, var1, etc. as they were in the function.

  2. To call another function and passing along a bunch of variables:

        # (inside function fun_a)
        kwargs = {k: v for k, v in locals().items() if k in 'arg0 arg1 arg2'.split()}
        fun_b(**kwargs)
    

Note that these are meant to be temporary quick & lazy tricks, not for production code!

Upvotes: 2

Related Questions