[Tutor] please return flys in ointment
Steven D'Aprano
steve at pearwood.info
Mon Jul 8 09:12:15 CEST 2013
Comments on your code inline below.
On Sat, Jul 06, 2013 at 02:38:27PM -0700, Jim Mooney wrote:
> import sys
>
> # Data
> ones = {'1': 'one', '2': 'two', '3': 'three', '4': 'four', '5': 'five',
> '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine'}
>
> tens = {'2': 'twenty', '3': 'thirty', '4': 'forty', '5': 'fifty', '6':
> 'sixty', '7': 'seventy', '8': 'eighty', '9': 'ninety'}
>
> doubles = {'0': 'ten', '1': 'eleven', '2': 'twelve', '3': 'thirteen', '4':
> 'fourteen', '5': 'fifteen', '6': 'sixteen', '7': 'seventeen', '8':
> 'eighteen', '9': 'nineteen'}
>
> powers_of_1000 = (' thousand', ' million', ' billion', ' trillion',
> ' quadrillion', ' quintillion', ' sextillion', ' septillion', ' octillion',
> ' nonillion', ' decillion')
>
> '''add these later, and also option for dollars-and-cents ending.
> 'vigintillion', 'novemdecillion', 'octodecillion', 'septendecillion',
> 'sexdecillion', 'quindecillion', 'quattuordecillion', 'tredecillion',
> 'duodecillion', 'undecillion',
> 'decillion', 'nonillion'
> '''
>
> # Functions
> def make_triplets_from_input():
> '''Enter a positive integer. A list of triplets in the same order will
> be returned.
> Raise ValueError to loop on non-integer input, or return 'zero'
> trigger-value of
> 'xxx' if all zeroes are entered. If input is okay, strip leading
> zeroes, then
> zero-pad leftmost triplet to three characters, so all slices are
> triplets. Adjust
> input for different Python versions.'''
> while True:
> try:
> if sys.version[0:3] == '2.7':
> numbers_str = original = raw_input('Enter a positive
> integer, space \
> separated if desired.')
> elif sys.version[0:3] == '3.3':
> numbers_str = original = input('Enter a positive integer,
> space \
> separated if desired.')
A better way to handle this is to perform a check once, outside the
function at the top of the file:
try:
raw_input
except NameError:
# Probably Python 3.
raw_input = input
and then just use raw_input inside the function. Or the other way
around, if you prefer:
try:
raw_input
except NameError:
pass
else:
input = raw_input
Then, inside the function, just unconditionally call:
result = input("Prompt, or 'quit' to exit: ")
result = result.lower().strip()
if result == 'quit':
break
> else:
> print('Python versions 2.7 and 3.3 only supported')
> sys.exit()
>
> numbers_str = ''.join(numbers_str.split())
> if numbers_str == '' or numbers_str == ' ': raise ValueError
Since you're splitting on whitespace, and joining with the empty string,
you cannot get numbers_str == ' '.
Besides, no need to explicitly check for '' here, since the very next
line will do so for you:
> numbers_int = int(numbers_str)
> if numbers_int == 0:
> print('Zero')
> sys.exit()
One should not treat "0" to mean "I want to quit".
> numbers_str = str(numbers_int)
> if len(numbers_str) > 36: raise ArithmeticError
ArithmeticError??? You're not doing arithmetic, how can this be an
arithmetic error?
You should be able to handle implausibly/arbitrarily long numbers, just
by chaining names (e.g. "billion billion billion billion..."). If you're
going to force some arbitrary limit on the number, and then use an
exception for flow-control (as you do here, catching ArithmeticError
further on), please use a custom exception so as to not confuse the
person reading your code.
> break
> except KeyboardInterrupt:
> print('Program cancelled by user')
> sys.exit()
/me lip curls
I'm not sure I like that...
> except ValueError as err:
> print(original, "is not an integer.")
> continue
> except ArithmeticError as err:
> print(original, "is too big.\n999...decillion is max: 10**37-1 or 36 chars \
> or 12 groups of 3 chars")
>
> leftpad = len(numbers_str) % 3 # zero-pad left, so we get all 3-character triplets
> if leftpad == 0: leftpad = ''
> elif leftpad == 2: leftpad = '0'
> else: leftpad = '00'
> numbers_str = leftpad + numbers_str
leftpad = len(numbers_str) % 3
if leftpad != 0:
leftpad = 3-leftpad
numbers_str = '0'*leftpad + numbers_str
> triplets = [numbers_str[x:x+3] for x in range(0,len(numbers_str),3)]
> return (triplets, len(triplets))
See also the recipe for "grouper" in the documentation for itertools.
--
Steven
More information about the Tutor
mailing list