How best to pass arbitrary parameters from one function to another

Steven D'Aprano steven at REMOVE.THIS.cybersource.com.au
Tue Sep 30 05:32:41 EDT 2008


On Tue, 30 Sep 2008 08:58:15 +0000, John O'Hagan wrote:

> Hi Pythonistas,
> 
> I'm looking for the best way to pass an arbitrary number and type of
> variables created by one function to another. They can't be global
> because they may have different values each time they are used in the
> second function.
> 
> So far I'm trying to do something like this:
> 
> 
> def process_args( [list, of, command-line, arguments] ):


If you are trying to process commandline args, I suggest you don't re-
invent the wheel. Have a look at the two standard modules, optparse and 
getopt. Of the two, getopt is probably simpler to get started with, but 
optparse is more powerful.


To answer your more general question, see below.


> 	do stuff
> 	return {dictionary : of, local : variables }
> 
> def main_function( **kwargs ):
> 
> 	do stuff
> 	return result
> 
> kw1 = process_args( [some, list] )
> kw2 = process_args( [a, different, list] )
> 
> for i in main_function( **kw1 ):
> 
> 	kw2[ var1 ] = i
> 	kw2[ var2 ] = len( i )
> 
> 	for j in main_function(**kw2):
> 
> 		print j
> 
> This only seems to work if I specify a default value for every possible
> parameter of main_function and also for any others which may be passed
> to it, which is a bit tedious because there are very many of them but
> only a few are used in any given execution of the program.

Er, yes. Presumably main_function actually does something. So it expects 
some arguments, and if the arguments aren't given, then it will fail. To 
prevent it failing when arguments aren't given, they must have default 
values. So define them, once, and be done with it:

def main_function(a=1, b=2, c=3, d=4):
    dostuff
    return result

Now this will work fine:

result = main_function( **{'a': 22, 'd': 33} )

and b and c will take their default values and everything works well. 
Default values are a feature, not a problem to be solved.



As for your nested for-loops (see above), I'm guessing that you're trying 
to copy items from one dictionary kw1 to another kw2, before processing 
kw2. You should check out the update method on dictionaries. Either of:

kw2.update(kw1)
kw1.update(kw2)

will probably do the right thing, depending on which values you want to 
take priority in the case of clashes. If you need something even more 
flexible, write a small function to merge the two dicts in whatever way 
you want. Here's one example:

def merge(kw1, kw2):
    """Merge dict kw1 to kw2 and return a new dict."""
    new = kw2.copy()
    for key, value in kw1.items():
        if key in kw2:
            # clash, keep the biggest value
            new[key] = max(value, kw2[key])
        else:
            new[key] = value
    return new




-- 
Steven



More information about the Python-list mailing list