Angus Rodgers wrote: >> Date: Sat, 04 Jul 2009 13:26:12 +0100 >> From: Angus Rodgers <ang...@bigfoot.com> >> Message-ID: <vrhu451924b136aea0ivadnlqc4h7uq...@4ax.com> >> >> <http://python.pastebin.com/d7e245e0f> (retention: 1 day) > > This is just a quick(ish!) response to the feedback so far. > > I realise, now, that I should have quoted what the exercise in the > book was asking for, to explain why my code is more elaborate than > the minimum that would be required to solve the problem at hand. > >>From the book (2nd ed., p. 151): > > "[...] we recommend that the reader convert his or her code to > functions that can be used in future exercises." > > This requirement was uppermost in my mind.
If it is the top requirement, then your code is not general enough as it can only ask for dictionaries. A general solution would be at least something like this: (now talk about bloat and overdesigning...) #!/usr/bin/env python import re from functools import partial ''' Like Swiss Army. It does everything. Includes batteries and kitchen sink. Caveat: written at 3AM in the morning. ''' class PromptError(Exception): pass def prompt(prompt='? ', reprompt='Invalid input. Try again.', validate=str, postprocess=str, tries=3, catchlist=(ValueError,), ): ''' prompt the user for input, validate, and return the result postprocess is called before returning the value if number of tries exceeds `tries` raise PromptError. Set tries to -1 to prompt infinitely ''' while tries != 0: inp = raw_input(prompt) try: validate(inp) except catchlist, e: print reprompt tries -= 1 else: return postprocess(inp) else: raise PromptError('Maximum number of tries exceeded') def expecting(s, expected=[], errmess='Invalid input'): ''' return True if `s` matches any regex pattern in `expected` raises ValueError otherwise. ''' for pat in expected: if re.compile(pat+'$', re.IGNORECASE).match(s): return True else: raise ValueError(errmess) def convert(s, convtab): ''' convert `s` into convtab's key ''' for target, pats in convtab.iteritems(): for pat in pats: if re.compile(pat+'$', re.IGNORECASE).match(s): return target else: raise ValueError('Cannot convert') def chain(*rings): ''' Calls a list of function and return their return values as a tuple ''' def _chain(): return tuple(ring() for ring in rings) return _chain def serial_prompt(mainprompt, cont_prompt='Continue? ', postprocess=lambda x: x, ): ''' Prompts for a series of values, with 'continue?'s between each prompt. Return values of the prompts are collected in a list and passed to `postprocess`. ''' def _serial_prompt(): ret = [mainprompt()] while get_bool(cont_prompt): ret.append(mainprompt()) return postprocess(ret) return _serial_prompt trues = ['1', 'ye?s?', 'tr?u?e?'] falses = ['0', 'no?', 'fa?l?s?e?'] bools = trues + falses expecting_bool = partial(expecting, expected=bools) convert_bool = partial(convert, convtab={True: trues, False: falses}) get_bool = partial(prompt, validate=expecting_bool, postprocess=convert_bool, ) get_key = prompt get_value = partial(prompt, validate=int, postprocess=int, ) get_kv = chain(partial(get_key, prompt='key (str): '), partial(get_value, prompt='value (int): '), ) get_dict = serial_prompt(get_kv, postprocess=dict) print get_bool('bool: ') print get_key('key (str): ') print get_value('value (int): ') print get_kv() print get_dict() _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor