The following code converts a number into Indian numbering system format.I know locale can also help in getting similar format but I wanted something that can work on any system because not all locales are present in all OSs.The code was written for Python 3.5 hence no variable annotations.from decimal import Decimalfrom itertools import islice, zip_longestfrom typing import Any, Iterable, Iterator, Sequence, Tuple, TypeVar, Union  # noqa: ignore=F401_T = TypeVar('_T')def grouper(iterable: Iterable[_T], n: int, fillvalue: Any = None) -> Iterator[Tuple[_T, ...]]:    Collect data into fixed-length chunks or blocks    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx    args = [iter(iterable)] * n    return zip_longest(fillvalue=fillvalue, *args)def indian_numbering_format(    amount: Union[Decimal, int, str], places: int = 2,    curr: str = '', pos: str = '', neg: str = '-') -> str:        Formats a number and returns it in Indian numbering format    https://en.wikipedia.org/wiki/Indian_numbering_system    places:  optional number of places after the decimal point    curr:    optional currency symbol before the sign    pos:     optional sign for positive numbers: '+' or blank    neg:     optional sign for negative numbers: '-' or blank    Note that if the fractional part only contains 0 it will be    dropped.        q = Decimal(10) ** -places  # type: Decimal    amount = Decimal(amount).quantize(q)    sign, digits, exponent = amount.as_tuple()    integer_part, fractional_part = (), ()  # type: Sequence[int], Sequence[int]    exponent = exponent or len(digits)    integer_part = digits[:exponent]    # If fractional part only contains 0s then ignore it.    if set(digits[exponent:]) != {0}:        fractional_part = digits[exponent:]    integer_part_digits = reversed(''.join(map(str, integer_part)))    thousand = ''.join(islice(integer_part_digits, 3))[::-1]    hundreds = ','.join(map(''.join, grouper(integer_part_digits, 2, fillvalue='')))[::-1]    sep = ',' if hundreds else ''    fractional_part_digits = '.' + ''.join([str(d) for d in fractional_part]) if fractional_part else ''    return '{sign}{curr}{hundreds}{sep}{thousand}{fractional_part}'.format(        sign=neg if sign else pos,        curr=curr,        thousand=thousand,        sep=sep,        hundreds=hundreds,        fractional_part=fractional_part_digits    )I was wondering if the code can be refactored in any way to make it much more simpler.
Indian numbering system formatting
python;python 3.x;formatting;fixed point
I don't think I'd get so fancy with the grouper; the data is small, a constant table will do:comma_after_digit = set(3, 5, 7, 9, 11, 13, 15, 17)result = '.' + ''.join(map(str, fractional_part))for i, d in enumerate(integer_part_digits):    if i in comma_after_digit:        result = ',' + result    result = d + resultresult = {0:pos, 1:neg}[sign] + resultreturn resultAlso:Try and be a bit more consistent: you use reversed() to reverse a string on one line, and then the next you use [::-1].  You also use map(str, digits) in one place and [str(x) for x in digits] another! They do the same thing, but it's nice to the reader to pick one idiom and stick with it.thousand = ''.join(islice(integer_part_digits, 3))[::-1] can be simplified into thousand = integer_part_digits[-4::-1]Using .format() is overkill for concatenating strings.  + works just fine.  If you want to use it, you should 1) factor out constant strings (like the decimal point) and 2) use the args as your temporary variables, like:return '{sign}{curr}{hundreds}{sep}{thousand}.{fractional_part}'.format(    sign=neg if sign else pos,    curr=curr,    thousand=integer_part_digits[-4::-1],    sep=',' if exponent > 3 else '',    hundreds=','.join(map(''.join, grouper(integer_part_digits, 2, fillvalue='')))[::-1],    fractional_part=''.join(map(str,fractional_part)) if fractional_part else '')According to the wikipedia page you cite, there's no comma after the 1 in 10**19, so your code is wrong :) ... which leads inevitably to:Needs tests!