error handling in user input: is this natural or just laborious

James Stroud jstroud at mbi.ucla.edu
Fri Oct 6 23:41:11 EDT 2006


James Stroud wrote:
> sam wrote:
> 
>> this does what i want, though i don't like the inner while loop having
>> to be there
[snip]
> A little cleaner. Now, lets tighten it up a bit more, and put nested 
> loops into functions. Im getting rid of keeping track of the running 
> total, that will clean a lot. I'm also going to be a little more 
> mathematically saavy.
> 
> def get_pct():
>   while True:
>     pct_list = ['cash', 'bond', 'blue', 'tech', 'dev']
>     pct_dict = get_pct_dict(pct_list)
>     total = sum(pct_dict.values())
>     if (total < 99.999) or (total > 100.001):
>       print "You've messed up, do it again"
>     else:
>       return pct_dict()
> 
> def get_pct_dict(pct_list):
>   pct_dict = {}
>   for a_pct in pct_list:
>     pct_dict[a_pct] = get_one_pct_value(a_pct)
>   return pct_dict()
> 
> def get_one_pct_value(a_pct):
>   msg = 'Please enter the percentage value for %s: '
>   while True:
>     try:
>        return float(msg % a_pct)
>     except ValueError:
>        print "You messed up, try again."
> 
> Now, all testing is done at the point where it is needed. There are no 
> running totals that could cause accounting errors, your final data 
> structure is an easy to use dict, unecessary tests have been eliminated, 
> loops have been de-nested visually and logically, and, most importantly, 
> the indentation level is kept manageable.
> 
> I think you will be able to see how this latter code evolved from yours. 
>  I used to program just like you and it has taken me a few years to 
> develop these little rules for tightening my code.
> 
> James
> 

Of course I see room for improvement in my own code.

Personally, I like to remove "values" from logic because it results, 
naturally, in more versatile functions. So I would redo my get_pct() 
method to take the list as a parameter:


def get_pct(pct_list):
   while True:
     pct_dict = get_pct_dict(pct_list)
     total = sum(pct_dict.values())
     if (total < 99.999) or (total > 100.001):
       print "You've messed up, do it again"
     else:
       return pct_dict()


Now, its a much more versatile piece of code, e.g.:


pct_list = ['cash', 'bond', 'blue', 'tech', 'dev']
pct_dict = get_pct(pct_list)


And now all of your code boils down to these latter 2 statments.

You might want to think about what you would do to pass the total 
criterion is as a parameter rather than hard coding it. Hint:

def get_pct(pct_list, criterion, slack):
   [you fill in here]
   if (total < (criterion - slack)) or {total > (criterion + slack)):
   [you fill in more here]

Now, no values are hard-coded but are passed in as parameters. Perhaps 
"msg" in get_one_pct_value() could be treated the same way to produce 
yet more flexibility and hence re-usability.

James

-- 
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/



More information about the Python-list mailing list