How best to pass arbitrary parameters from one function to another

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • John O'Hagan

    How best to pass arbitrary parameters from one function to another

    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] ):

    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.

    Is there a better way to do it? Or have I simply made an error?

    Regards and thanks,

    John O'Hagan
  • Bruno Desthuilliers

    #2
    Re: How best to pass arbitrary parameters from one function to another

    John O'Hagan a écrit :
    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] ):
    >
    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.
    If this is about commmand line arguments parsing and defaults, you may
    want to have a look at the optparse package in the stdlib.

    Also, kwargs work fine with default arguments too, ie:


    def func(arg1=1, arg2='yadda', arg3=None):
    print arg1, arg2, arg3

    for kw in ({}, {'arg1':42}, {'arg2':'yop', 'arg3' : range(5)}):
    func(**kw)

    HTH

    Comment

    • Steven D'Aprano

      #3
      Re: How best to pass arbitrary parameters from one function toanother

      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

      Comment

      Working...