Inspired by the recent surge of questions dealing with changing numbers to their English equivalents (See here, here, and here), I decided to write my own version in Python.zero_to_nineteen = (    zero,    one,    two,    three,    four,    five,    six,    seven,    eight,    nine,    ten,    eleven,    twelve,    thirteen,    fourteen ,    fifteen,    sixteen,    seventeen,    eighteen,    nineteen)tens = (    zero,    ten,    twenty,    thirty,    forty,    fifty,    sixty,    seventy,    eighty,    ninety)suffixes = {    3 : thousand,    6 : million,    9 : billion,    12 : trillion,    15 : quadrillion,    18 : quintillion,    21 : sextillion,    24 : septillion,    27 : octillion,    30 : nonillion,    33 : decillion,    36 : undecillion    39 : duodecillion,    42 : tredicillion,    45 : quattuordecillion,    48 : quinquadecillion,    51 : sedecillion,    54 : septendecillion,    57 : octodecillion,    60 : novendecillion,    63 : vigintillion,    66 : unvigintillion,    69 : duovigintillion,    72 : tresvigintillion,    75 : quattuorvigintillion,    78 : quinquavigintillion,    81 : sesvigintillion,    84 : septemvigintillion,    87 : octovigintillion,    90 : novemvigintillion,    93 : trigintillion,    96 : untrigintillion,    99 : duotrigintillion,    102 : trestrigintilion,    105 : quattuortrigintillion,    108 : quinquatrigintillion,    111 : sestrigintillion,    114 : septentrigintillion,    117 : octotrigintillion,    120 : noventrigintillion,    123 : quadragintillion}def spell_out(number):    Returns a string representation of the number, in english    if isinstance(number, float):        raise ValueError(number must be an integer)    if number < 0:        return negative  + spell_out(-1 * number)    if number < 20:        return zero_to_nineteen[number]    if number < 100:        tens_digit = number // 10        ones_digit = number % 10        if ones_digit == 0:            return tens[tens_digit]        else:            return {}-{}.format(tens[tens_digit], zero_to_nineteen[ones_digit])    if number < 1000:        hundreds_digit = zero_to_nineteen[number // 100]        rest = number % 100        if rest == 0:            return {} hundred.format(hundreds_digit)        else:            return {} hundred {}.format(hundreds_digit, spell_out(rest))    suffix_index = log(number)    suffix_index -= suffix_index % 3    prefix = spell_out(number // 10 ** suffix_index)    suffix = suffixes[suffix_index]    rest_of_number = number % (10 ** suffix_index)    if suffix_index in suffixes:        if number % (10 ** suffix_index) == 0:            return {} {}.format(prefix, suffix)        else:            return {} {} {}.format(prefix, suffix, spell_out(rest_of_number))    return infinitydef log(number):    Returns integer which is log base 10 of number    answer = 0    while number > 9:        answer += 1        number //= 10    return answerI would appreciate any comments on my code.
Numbers to English Strings in Python3
python;python 3.x;converting
Following up on Davidmh's answer, here are some other improvements:Consistency:Instead of using tuples for only tens and zero_to_nineteen, stay consistent and use it for the suffixes as well, by making it 1000's based. Aka, the indices would correspond to the power of a thousand that the number relates to. For example, 1000 could be 1st element, while 10 ** 30 would be the 10th.Code Style:Your code repeatedly utilizes blocks of the format:a = number // xb = number % xThis can be simplified down using Python's built-int divmod function like so:a, b = divmod(number, x)Also, your code repeatedly uses code segments like this:if second_part == 0:    return first_partelse:    return first_part + separator + second_partYou are violating the DRY principle by doing this and should instead abstract this logic out into a function of its own like so:def _create_number(prefix, suffix, seperator= ):    # Returns a number with given prefix and suffix (if needed)    if not isinstance(prefix, str):        prefix = spell_out(prefix)    return prefix if suffix == 0 else prefix + seperator + spell_out(suffix)Other Suggestions:Normally, numbers are expected to be separated by commas. So one million three hundred thousand forty-five would be one million, three hundred thousand, forty-five. This is easy to do with the suggested function, as you simply make the seperator ,  instead of  . Instead of fumbling around with floats and such, let Python handle it via int() and then the only thing you would want to catch is when that throws an OverflowError for large floating point values (like 1e584). This is done like so:try:    number = int(number)except OverflowError:    # This will be triggered if trying to use this with numbers like 1e584    return infinityPython will raise a ValueError automatically anyways if it's not something that can be interpreted by int(). This code also has the benefit of being a bit more future-proof. If int() will start to work with tuples or other data types someday (aka (1, 2, 3) could become 123), then this code will still work.Lastly, you could add a special case for a thousand, and then remove the -illion from each of the suffixes for a more compact form.