[Tutor] Simulating case statement

2005-09-27 Thread Jan Eden
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.

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
-- 
Common sense is what tells you that the world is flat.
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Simulating case statement

2005-09-27 Thread Kent Johnson
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

___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Simulating case statement

2005-09-27 Thread Jan Eden
Kent Johnson wrote on 27.09.2005:

Jan Eden wrote:

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:

I see. I did not know that I can use a formal parameter **param in calls - 
thought I could only do so in function definitions:

def func(**param):
...

 func(id=1, stuff='blah')
 
 Thanks for that!
 
 Jan
-- 
Mac OS X. Because making Unix user-friendly is easier than debugging Windows.
___
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor