[Tutor] Simulating case statement

Kent Johnson kent37 at tds.net
Tue Sep 27 13:56:33 CEST 2005


Jan Eden wrote:
> Hi,
> 
> I used to use an extended if...elif sequence to instantiate an object and call this object's display method afterwards:
> ####
> if safe['type'] == pages:
>     page = Show.Page(id=safe['id'], start=safe['start'] ...),
> elif safe['type'] == pages:
>     author = Show.Author(id=safe['id']...)
>  ...
> 
> page.Display()
> #### 
> 
> To improve readability, I changed this code to use a dictionary:
> 
> ####
> valid_types = dict(
>     pages=Show.Page,
>     authors=Show.Author,
>     ...
> )
> 
> page = valid_types[safe_parameters['type']](safe_parameters)
> page.Display()
> ####
> 
> The problem is that the __init__ methods of the respective classes
> take a different number of parameters - this is why I pass the whole
> safe_parameters dictionary.

I think if you pass the dictionary as keyword arguments rather than as a single dict you will get what you want.
page = valid_types[safe_parameters['type']](**safe_parameters)

This syntax means, use safe_parameters to populate the keyword arguments of the function. Any parameters which are not in safe_parameters will be set to their default values, and in other calls you can set the parameters as you like. Here is a simple example:

 >>> def f1(id='123', value='abc', **kwds):
 ...   print 'id =', id
 ...   print 'value =', value
 ...
 >>> def f2(id='345', stuff='nonsense', **kwds):
 ...   print 'id =', id
 ...   print 'stuff =', stuff
 ...
 ...
 >>> params = dict(id=3, value='def')
 >>> f1(**params)
id = 3
value = def
 >>> f2(**params)
id = 3
stuff = nonsense
 >>> f1()
id = 123
value = abc
 >>> f1(value=34)
id = 123
value = 34

The **kwds parameter to the function is needed to allow the extra parameters in the passed dictionary. Otherwise you will get a TypeError:

 >>> def f3(id='345', stuff='nonsense'):
 ...   print 'id =', id
 ...   print 'stuff =', stuff
 ...
 >>> f3(**params)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: f3() got an unexpected keyword argument 'value'

Kent

> 
> This has a number of drawbacks when instantiating an object in other
> situations because I cannot use a default for some parameters while
> passing some others.
> 
> So I'd like to do pass the parameters individually, based on the
> class. I know I would need to expand the valid_types dictionary to
> include the parameters - but how can I pass these one by one?> 
> What I came up with is a monster (which does not work anyway):
> 
> valid_types = dict(
>     pages=dict(klasse=Show.Page, parameters=dict(id=safe['id'], start=safe['start'] ...))
>     authors=dict(klasse=Show.Author, ...)
>     ...
> )
> 
> page = valid_types[safe_parameters['type']]['klasse'](valid_types['parameters'])
> 
> page.Display()
> 
> How can I circumvent the if...elif sequence and have the parameters passed individually at the same time?
> 
> Thanks for any suggestions,
> 
> Jan



More information about the Tutor mailing list