Newbie: How can I use a string value for a keyword argument?

Doug Morse morse at edoug.org
Mon Feb 25 13:41:59 CET 2008


On Mon, 25 Feb 2008 04:20:37 -0800 (PST), John Machin <sjmachin at lexicon.net>
wrote:
>  On Feb 25, 10:42 pm, Doug Morse <mo... at edoug.org> wrote:
> > Hi,
> >
> > My apologies for troubling for what is probably an easy question... it's just
> > that can't seem to find an answer to this anywhere (Googling, pydocs, etc.)...
> >
> > I have a class method, MyClass.foo(), that takes keyword arguments.  For
> > example, I can say:
> >
> > x = MyClass()
> > x.foo(trials=32)
> >
> > Works just fine.
> >
> > What I need to be able to do is call foo() with a string value specifying the
> > keyword (or both the keyword and value would be fine), something along the
> > lines of:
> >
> > x = MyClass()
> > y = 'trials=32'
> > x.foo(y)        # doesn't work
> >
> > or
> >
> > x.MyClass()
> > y = 'trials'
> > x.foo(y = 32)   # does the "wrong" thing
> >
> > Surely there's some way to use a string's value as the key for making a method
> > call with a keyword argument?
> >
> > Just for completeness, my goal is simply to read a bunch of key/value pairs
> > from an INI file (using ConfigObj) and then use those key/value pairs to set a
> > (3rd party) object's parameters, which must be done with a call along the
> > lines of "instance.set(key=value)".  Obviously, I could create a huge if..elif
> > statement along the lines of "if y = 'trials': x.foo(trials=32); elif y =
> > 'speed': x.foo(speed=12);" etc., but then the statement has to be maintained
> > every time a new parameter is added/changed etc.  Plus, such a solution seems
> > to me grossly inelegant and un-Pythonic.
> >
> 
>  I'm not quite sure what foo() is really supposed to do ... however the
>  built-in function setattr is your friend. Assuming that ini_dict
>  contains what you have scraped out of your .ini file, you can do:
>      x = MyCLass()
>      for key, value in ini_dict.items():
>          setattr(x, key, value)
>  You may prefer (I would) to do it inside the class, and maybe do some
>  checking/validation:
>      class MyClass(object):
>          def load(self, adict):
>              for k, v in adict.items():
>                  # do checking here
>                  setattr(self, k, v)
>     # much later
>     x = MyClass()
>     x.load(ini_dict)
> 
>  HTH,
>  John

Hi John,

Your response is most helpful and informative -- thanks!  

I don't think that setattr() is exactly what I need, though, as foo() doesn't
actually create or update its instance attributes.  What I need to be able to
do is call foo() specifying keyword arguments not directly but viz a viz
another variable or variables that contain the keywords and values.

I'm pretty sure I just found the solution, which is to use the **-operator on
a dictionary.  Actually, ConfigObj (the INI file reader) subclasses from
__builtin__.dict (i.e., the class/object *is* a dictionary), so the following
seems to work perfectly:

x.foo(**config)

This sends ALL the key/value pairs in config as keyword/value pairs to foo(),
which is exactly what I need.

Just FYI, I located this solution via Google shortly after posting, so I have
sent a cancel request on my original post.

Thanks again!
Doug



More information about the Python-list mailing list