unexplainable python

Dave Angel davea at ieee.org
Sun Sep 27 00:58:30 EDT 2009


dads wrote:
> When creating a script that converts digits to words I've come across
> some unexplainable python. The script works fine until I use a 5 digit
> number and get a 'IndexError: string index out of range'. After
> looking into it and adding some print calls, it looks like a variable
> changes for no reason. The example beneath is using the digits 34567,
> the _5digit function slices 34 off and passes it to the _2digit
> function, which works with 2 digit strings but the IndexError is
> raised. Please accept my apologies for the explanation, I'm finding it
> hard to put into words. Has anyone any idea why it's acting the way it
> is?
>
> enter number: 34567
> _5digit function used
> 34 before sent to _2digit
> 34 slice when at _2digit function
> 34 before sent to plus_ten function
> 7 slice when at _2digit function
> 7 before sent to plus_ten function
>
>
> from __future__ import print_function
> import sys
>
> class number(object):
>
>     def __init__(self, number):
>
>         #remove any preceding zero's
>         num = int(number)
>         self.num = str(num)
>         self.num = number
>
>         self.single =
> {'0':'zero','1':'one','2':'two','3':'three','4':'four',
>  
> '5':'five','6':'six','7':'seven','8':'eight','9':'nine'}
>         self.teen = {'11':'eleven','12':'twelve','13':'thirteen',
>                       '14':'fourteen','15':'fifteen','16':'sixteen',
>  
> '17':'seventeen','18':'eighteen','19':'nineteen'}
>         self.plus_ten =
> {'10':'ten','20':'twenty','30':'thirty','40':'forty',
>                           '50':'fifty','60':'sixty','70':'seventy',
>                           '80':'eighty','90':'ninety'}
>         self._translate()
>
>     def _translate(self):
>
>         fns = [ i for i in number.__dict__ if 'digit' in i ]
>         fns.sort()
>         fn_name = fns[len(self.num)-1]
>         print(fn_name,'function used')
>         fn = number.__dict__[fn_name]
>         print(fn(self, self.num))
>
>
>     def _1digit(self, n):
>
>         return self.single[n]
>
>     def _2digit(self, n):
>
>         print(n, 'slice when at _2digit function')
>         if '0' in self.num:
>             return self.plus_ten[n]
>         elif self.num[0] == '1':
>             return self.teen[n]
>         else:
>             print(n,'before sent to plus_ten function')
>             var = self.plus_ten[n[0]+'0'] + ' ' + self._1digit(n[1])
>             return var
>
>     def _3digit(self, n):
>
>         var = self._1digit(n[0]) + ' hundred and ' + self._2digit(n
> [1:])
>         return var
>
>     def _4digit(self, n):
>
>         var = self._1digit(n[0]) + ' thousand ' + self._3digit(n[1:])
>         return var
>
>
>     def _5digit(self, n):
>
>         print(n[:2],'before sent to _2digit')
>         var = self._2digit(n[:2]) + ' thousand ' + self._4digit(n[2:])
>         return var
>
> class control(object):
>
>     def __init__(self):
>         pass
>
>     def data_input(self):
>
>
>         while True:
>             i = raw_input('enter number: ')
>             if i == 's':
>                 break
>             #try:
>             n = number(i)
>             #except:
>             #    print('not a number')
>
>
> if __name__ in '__main__':
>     c = control()
>     c.data_input()
>
>   
This program would be much simpler if you didn't use classes.   So far, 
they don't contribute anything but obfuscation.

Random observations:
in _2digit(), line:
   if '0' in self.num

test makes no sense.  Presumably what you really are trying to check is 
whether the low digit of n is zero.  But in fact you're checking whether 
any of the 5 digits of the whole number is 0.

in _5digit(), line:
           var = self._2digit(n[:2]) + ' thousand ' + self._4digit(n[2:])

should be calling self._3digit(),  not self._4digit().  I presume that's 
the immediate cause of your error.  You'll notice that _4digit() calls 
_2digit(), but by that time the problem has already been triggered.

DaveA






More information about the Python-list mailing list