Как вывести число с запятыми в качестве разделителей тысяч?

StackOverflow https://stackoverflow.com/questions/1823058

  •  10-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь напечатать целое число в Python 2.6.1 с запятыми в качестве разделителей тысяч.Например, я хочу показать номер 1234567 как 1,234,567.Как бы я это сделал?Я видел много примеров в Google, но я ищу самый простой практический способ.

Для выбора между точками и запятыми не обязательно зависеть от конкретной локали.Я бы предпочел что-нибудь как можно более простое.

Это было полезно?

Решение

Локаль не известна

'{:,}'.format(value)  # For Python ≥2.7
f'{value:,}'  # For Python ≥3.7

Знание локали

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')  # Customize

'{:n}'.format(value)  # For Python ≥2.7
f'{value:n}'  # For Python ≥3.7

Ссылка

За мини-язык спецификации формата ,

  

Опция ',' указывает на использование запятой для разделителя тысяч. Для разделителя, поддерживающего локали, используйте вместо этого целочисленный тип представления 'n'.

Другие советы

Я заставил это сработать:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US')
'en_US'
>>> locale.format("%d", 1255000, grouping=True)
'1,255,000'

Конечно, ты этого не делаешь потребность поддерживается интернационализация, но она понятна, лаконична и использует встроенную библиотеку.

P.S.Этот "%d" - обычный форматировщик в стиле %.У вас может быть только один форматировщик, но он может быть любым, что вам нужно с точки зрения ширины поля и настроек точности.

P.P.S.Если ты не можешь получить locale чтобы работать, я бы предложил измененную версию ответа Марка:

def intWithCommas(x):
    if type(x) not in [type(0), type(0L)]:
        raise TypeError("Parameter must be an integer.")
    if x < 0:
        return '-' + intWithCommas(-x)
    result = ''
    while x >= 1000:
        x, r = divmod(x, 1000)
        result = ",%03d%s" % (r, result)
    return "%d%s" % (x, result)

Рекурсия полезна для отрицательного случая, но одна рекурсия на запятую кажется мне немного чрезмерной.

За неэффективность и нечитаемость трудно победить:

>>> import itertools
>>> s = '-1234567'
>>> ','.join(["%s%s%s" % (x[0], x[1] or '', x[2] or '') for x in itertools.izip_longest(s[::-1][::3], s[::-1][1::3], s[::-1][2::3])])[::-1].replace('-,','-')

Вот код группирования локали после удаления ненужных частей и его небольшой очистки:

(следующее работает только для целых чисел)

def group(number):
    s = '%d' % number
    groups = []
    while s and s[-1].isdigit():
        groups.append(s[-3:])
        s = s[:-3]
    return s + ','.join(reversed(groups))

>>> group(-23432432434.34)
'-23,432,432,434'
<Ч>

Здесь уже есть несколько хороших ответов. Я просто хочу добавить это для дальнейшего использования. В Python 2.7 будет указатель формата для разделителя тысяч. Согласно документации по питону это работает так

>>> '{:20,.2f}'.format(f)
'18,446,744,073,709,551,616.00'

В python3.1 вы можете сделать то же самое, как это:

>>> format(1234567, ',d')
'1,234,567'

Я удивлен, что никто не упомянул, что вы можете сделать это с помощью f-строк в Python 3.6 так же просто, как это:

>>> num = 10000000
>>> print(f"{num:,d}")
10,000,000

... где часть после двоеточия является спецификатором формата. Запятая - это требуемый символ-разделитель, поэтому f"{num:_d}" вместо запятой используются подчеркивания.

Это эквивалентно использованию format(num, ",d") для более старых версий Python 3.

Вот замена регулярного выражения в одну строку:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)

Работает только для интегральных выходов:

import re
val = 1234567890
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
# Returns: '1,234,567,890'

val = 1234567890.1234567890
# Returns: '1,234,567,890'

Или для чисел с плавающей точкой менее 4 цифр измените спецификатор формата на %.3f:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.3f" % val)
# Returns: '1,234,567,890.123'

Примечание: неправильно работает с более чем тремя десятичными цифрами, так как будет пытаться сгруппировать десятичную часть:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.5f" % val)
# Returns: '1,234,567,890.12,346'

Как это работает

Давайте разберемся с этим:

re.sub(pattern, repl, string)

pattern = \
    "(\d)           # Find one digit...
     (?=            # that is followed by...
         (\d{3})+   # one or more groups of three digits...
         (?!\d)     # which are not followed by any more digits.
     )",

repl = \
    r"\1,",         # Replace that one digit by itself, followed by a comma,
                    # and continue looking for more matches later in the string.
                    # (re.sub() replaces all matches it finds in the input)

string = \
    "%d" % val      # Format the string as a decimal to begin with

Это то, что я делаю для поплавков. Хотя, если честно, я не уверен, для каких версий он работает - я использую 2.7:

my_number = 4385893.382939491

my_string = '{:0,.2f}'.format(my_number)

Возвращает: 4 385 893,38

Обновление: у меня недавно была проблема с этим форматом (я не мог сказать вам точную причину), но я смог ее исправить, опустив 0:

my_string = '{:,.2f}'.format(my_number)

Вы также можете использовать '{:n}'.format( value ) для представления языкового стандарта.Я думаю, что это самый простой способ для решения проблемы локализации.

Для получения дополнительной информации выполните поиск по thousands в Python ДОК.

В качестве валюты вы можете использовать locale.currency, устанавливающий флаг grouping:

Код

import locale

locale.setlocale( locale.LC_ALL, '' )
locale.currency( 1234567.89, grouping = True )

Выходной сигнал

'Portuguese_Brazil.1252'
'R$ 1.234.567,89'

Я уверен, что для этого должна быть стандартная библиотечная функция, но было интересно попробовать написать ее самостоятельно, используя рекурсию, поэтому вот что я придумала:

def intToStringWithCommas(x):
    if type(x) is not int and type(x) is not long:
        raise TypeError("Not an integer!")
    if x < 0:
        return '-' + intToStringWithCommas(-x)
    elif x < 1000:
        return str(x)
    else:
        return intToStringWithCommas(x / 1000) + ',' + '%03d' % (x % 1000)

Сказав это, если кто-то другой найдет стандартный способ сделать это, вы должны использовать его вместо этого.

Из комментариев рецепт активного состояния 498181 Я переделал это:

import re
def thous(x, sep=',', dot='.'):
    num, _, frac = str(x).partition(dot)
    num = re.sub(r'(\d{3})(?=\d)', r'\1'+sep, num[::-1])[::-1]
    if frac:
        num += dot + frac
    return num

Он использует функцию регулярных выражений: lookahead , т. е. (?=\d) чтобы убедиться, что только группы из трех цифр, которые имеют цифру «после», получат запятую. Я говорю «после», потому что на этом этапе строка обратная.

[::-1] просто переворачивает строку.

Немного расширяю ответ Яна Шнайдера:

Если вы хотите использовать пользовательский разделитель тысяч, самое простое решение:

'{:,}'.format(value).replace(',', your_custom_thousands_separator)

Примеры

'{:,.2f}'.format(123456789.012345).replace(',', ' ')

Если вы хотите, чтобы немецкое представление было таким, оно становится немного сложнее:

('{:,.2f}'.format(123456789.012345)
          .replace(',', ' ')  # 'save' the thousands separators 
          .replace('.', ',')  # dot to comma
          .replace(' ', '.')) # thousand separators to dot

Python 3

--

Целые числа (без десятичной дроби):

"{:,d}".format(1234567)

--

Плавающие значения (с десятичной запятой):

"{:,.2f}".format(1234567)

где число , указанное ранее f задает количество знаков после запятой.

--

Бонус

Функция быстрого запуска для индийской системы нумерации лакхов / крор (12 34 567):

https://stackoverflow.com/a/44832241/4928578

Принятый ответ - хорошо, но я на самом деле предпочитаю format(number,','). Мне легче интерпретировать и запомнить.

https://docs.python.org/3/library/functions. HTML # формат

начиная с Python версии 2.6, вы можете сделать это:

def format_builtin(n):
    return format(n, ',')

Для версий Python < 2.6 и просто для вашей информации, вот 2 ручных решения, они превращают значения с плавающей точкой в целые числа, но отрицательные числа работают корректно:

def format_number_using_lists(number):
    string = '%d' % number
    result_list = list(string)
    indexes = range(len(string))
    for index in indexes[::-3][1:]:
        if result_list[index] != '-':
            result_list.insert(index+1, ',')
    return ''.join(result_list)

здесь стоит обратить внимание на несколько вещей:

  • эта линия: строка = '%d' % число прекрасно преобразует число в строку, поддерживает отрицательные значения и удаляет дроби из чисел с плавающей точкой, превращая их в целые числа;
  • этот кусочек индексы [::-3] возвращает каждый третий элемент, начиная с конца, поэтому я использовал другой фрагмент [1:] чтобы убрать самый последний элемент потому что мне не нужна запятая после последнего числа;
  • этот условный если l[индекс] != '-' используется для поддержки отрицательных чисел, не вставляйте запятую после знака минус.

И более хардкорная версия:

def format_number_using_generators_and_list_comprehensions(number):
    string = '%d' % number
    generator = reversed( 
        [
            value+',' if (index!=0 and value!='-' and index%3==0) else value
            for index,value in enumerate(reversed(string))
        ]
    )
    return ''.join(generator)

Вот тот, который работает и для поплавков:

def float2comma(f):
    s = str(abs(f)) # Convert to a string
    decimalposition = s.find(".") # Look for decimal point
    if decimalposition == -1:
        decimalposition = len(s) # If no decimal, then just work from the end
    out = "" 
    for i in range(decimalposition+1, len(s)): # do the decimal
        if not (i-decimalposition-1) % 3 and i-decimalposition-1: out = out+","
        out = out+s[i]      
    if len(out):
        out = "."+out # add the decimal point if necessary
    for i in range(decimalposition-1,-1,-1): # working backwards from decimal point
        if not (decimalposition-i-1) % 3 and decimalposition-i-1: out = ","+out
        out = s[i]+out      
    if f < 0:
        out = "-"+out
    return out

Пример использования:

>>> float2comma(10000.1111)
'10,000.111,1'
>>> float2comma(656565.122)
'656,565.122'
>>> float2comma(-656565.122)
'-656,565.122'

Один вкладыш для Python 2.5+ и Python 3 (только положительный int):

''.join(reversed([x + (',' if i and not i % 3 else '') for i, x in enumerate(reversed(str(1234567)))]))

Я новичок в Python, но опытный программист. У меня есть Python 3.5, поэтому я могу просто использовать запятую, но это, тем не менее, интересное упражнение по программированию. Рассмотрим случай целого числа без знака. Наиболее читаемая программа Python для добавления разделителей тысяч выглядит так:

def add_commas(instr):
    out = [instr[0]]
    for i in range(1, len(instr)):
        if (len(instr) - i) % 3 == 0:
            out.append(',')
        out.append(instr[i])
    return ''.join(out)

Также можно использовать понимание списка:

add_commas(instr):
    rng = reversed(range(1, len(instr) + (len(instr) - 1)//3 + 1))
    out = [',' if j%4 == 0 else instr[-(j - j//4)] for j in rng]
    return ''.join(out)

Это короче, и может быть одним вкладышем, но вам придется сделать небольшую гимнастическую гимнастику, чтобы понять, почему это работает. В обоих случаях мы получаем:

for i in range(1, 11):
    instr = '1234567890'[:i]
    print(instr, add_commas(instr))
1 1
12 12
123 123
1234 1,234
12345 12,345
123456 123,456
1234567 1,234,567
12345678 12,345,678
123456789 123,456,789
1234567890 1,234,567,890

Первая версия - более разумный выбор, если вы хотите, чтобы программа была понятна.

Это делает деньги вместе с запятыми

def format_money(money, presym='$', postsym=''):
    fmt = '%0.2f' % money
    dot = string.find(fmt, '.')
    ret = []
    if money < 0 :
        ret.append('(')
        p0 = 1
    else :
        p0 = 0
    ret.append(presym)
    p1 = (dot-p0) % 3 + p0
    while True :
        ret.append(fmt[p0:p1])
        if p1 == dot : break
        ret.append(',')
        p0 = p1
        p1 += 3
    ret.append(fmt[dot:])   # decimals
    ret.append(postsym)
    if money < 0 : ret.append(')')
    return ''.join(ret)

У меня есть версии этого кода на python 2 и python 3.Я знаю, что вопрос был задан для python 2, но теперь (8 лет спустя, lol) люди, вероятно, будут использовать python 3.

Код на Python 3:

import random
number = str(random.randint(1, 10000000))
comma_placement = 4
print('The original number is: {}. '.format(number))
while True:
    if len(number) % 3 == 0:
        for i in range(0, len(number) // 3 - 1):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
            comma_placement = comma_placement + 4
    else:
        for i in range(0, len(number) // 3):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
    break
print('The new and improved number is: {}'.format(number))        


Код на Python 2:(Правка.Код python 2 не работает.Я думаю, что синтаксис другой).

import random
number = str(random.randint(1, 10000000))
comma_placement = 4
print 'The original number is: %s.' % (number)
while True:
    if len(number) % 3 == 0:
        for i in range(0, len(number) // 3 - 1):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
            comma_placement = comma_placement + 4
    else:
        for i in range(0, len(number) // 3):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
    break
print 'The new and improved number is: %s.' % (number) 

Я использую Python 2.5, поэтому у меня нет доступа к встроенному форматированию.

Я посмотрел на intcomma кода Django (intcomma_recurs в приведенном ниже коде) и понял, что он неэффективен, потому что он рекурсивный, а также компиляция регулярного выражения при каждом запуске тоже не очень хорошая вещь. Это не является обязательным «вопросом», так как Django на самом деле НЕ ТОЧНО сосредоточен на такого рода низкоуровневой производительности. Кроме того, я ожидал разницы в производительности в 10 раз, но она только в 3 раза медленнее.

Из любопытства я реализовал несколько версий intcomma, чтобы увидеть преимущества производительности при использовании регулярных выражений. Мои тестовые данные показывают небольшое преимущество для этой задачи, но на удивление совсем немного.

Мне также было приятно увидеть то, что я подозревал: использование подхода обратного смещения не требуется в случае отсутствия регулярных выражений, но он делает код немного лучше при стоимости ~ 10% производительности.

Кроме того, я предполагаю, что вы передаете строку и выглядит как число. Результаты не определены иначе.

from __future__ import with_statement
from contextlib import contextmanager
import re,time

re_first_num = re.compile(r"\d")
def intcomma_noregex(value):
    end_offset, start_digit, period = len(value),re_first_num.search(value).start(),value.rfind('.')
    if period == -1:
        period=end_offset
    segments,_from_index,leftover = [],0,(period-start_digit) % 3
    for _index in xrange(start_digit+3 if not leftover else start_digit+leftover,period,3):
        segments.append(value[_from_index:_index])
        _from_index=_index
    if not segments:
        return value
    segments.append(value[_from_index:])
    return ','.join(segments)

def intcomma_noregex_reversed(value):
    end_offset, start_digit, period = len(value),re_first_num.search(value).start(),value.rfind('.')
    if period == -1:
        period=end_offset
    _from_index,segments = end_offset,[]
    for _index in xrange(period-3,start_digit,-3):
        segments.append(value[_index:_from_index])
        _from_index=_index
    if not segments:
        return value
    segments.append(value[:_from_index])
    return ','.join(reversed(segments))

re_3digits = re.compile(r'(?<=\d)\d{3}(?!\d)')
def intcomma(value):
    segments,last_endoffset=[],len(value)
    while last_endoffset > 3:
        digit_group = re_3digits.search(value,0,last_endoffset)
        if not digit_group:
            break
        segments.append(value[digit_group.start():last_endoffset])
        last_endoffset=digit_group.start()
    if not segments:
        return value
    if last_endoffset:
        segments.append(value[:last_endoffset])
    return ','.join(reversed(segments))

def intcomma_recurs(value):
    """
    Converts an integer to a string containing commas every three digits.
    For example, 3000 becomes '3,000' and 45000 becomes '45,000'.
    """
    new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', str(value))
    if value == new:
        return new
    else:
        return intcomma(new)

@contextmanager
def timed(save_time_func):
    begin=time.time()
    try:
        yield
    finally:
        save_time_func(time.time()-begin)

def testset_xsimple(func):
    func('5')

def testset_simple(func):
    func('567')

def testset_onecomma(func):
    func('567890')

def testset_complex(func):
    func('-1234567.024')

def testset_average(func):
    func('-1234567.024')
    func('567')
    func('5674')

if __name__ == '__main__':
    print 'Test results:'
    for test_data in ('5','567','1234','1234.56','-253892.045'):
        for func in (intcomma,intcomma_noregex,intcomma_noregex_reversed,intcomma_recurs):
            print func.__name__,test_data,func(test_data)
    times=[]
    def overhead(x):
        pass
    for test_run in xrange(1,4):
        for func in (intcomma,intcomma_noregex,intcomma_noregex_reversed,intcomma_recurs,overhead):
            for testset in (testset_xsimple,testset_simple,testset_onecomma,testset_complex,testset_average):
                for x in xrange(1000): # prime the test
                    testset(func)
                with timed(lambda x:times.append(((test_run,func,testset),x))):
                    for x in xrange(50000):
                        testset(func)
    for (test_run,func,testset),_delta in times:
        print test_run,func.__name__,testset.__name__,_delta

А вот и результаты теста:

intcomma 5 5
intcomma_noregex 5 5
intcomma_noregex_reversed 5 5
intcomma_recurs 5 5
intcomma 567 567
intcomma_noregex 567 567
intcomma_noregex_reversed 567 567
intcomma_recurs 567 567
intcomma 1234 1,234
intcomma_noregex 1234 1,234
intcomma_noregex_reversed 1234 1,234
intcomma_recurs 1234 1,234
intcomma 1234.56 1,234.56
intcomma_noregex 1234.56 1,234.56
intcomma_noregex_reversed 1234.56 1,234.56
intcomma_recurs 1234.56 1,234.56
intcomma -253892.045 -253,892.045
intcomma_noregex -253892.045 -253,892.045
intcomma_noregex_reversed -253892.045 -253,892.045
intcomma_recurs -253892.045 -253,892.045
1 intcomma testset_xsimple 0.0410001277924
1 intcomma testset_simple 0.0369999408722
1 intcomma testset_onecomma 0.213000059128
1 intcomma testset_complex 0.296000003815
1 intcomma testset_average 0.503000020981
1 intcomma_noregex testset_xsimple 0.134000062943
1 intcomma_noregex testset_simple 0.134999990463
1 intcomma_noregex testset_onecomma 0.190999984741
1 intcomma_noregex testset_complex 0.209000110626
1 intcomma_noregex testset_average 0.513000011444
1 intcomma_noregex_reversed testset_xsimple 0.124000072479
1 intcomma_noregex_reversed testset_simple 0.12700009346
1 intcomma_noregex_reversed testset_onecomma 0.230000019073
1 intcomma_noregex_reversed testset_complex 0.236999988556
1 intcomma_noregex_reversed testset_average 0.56299996376
1 intcomma_recurs testset_xsimple 0.348000049591
1 intcomma_recurs testset_simple 0.34600019455
1 intcomma_recurs testset_onecomma 0.625
1 intcomma_recurs testset_complex 0.773999929428
1 intcomma_recurs testset_average 1.6890001297
1 overhead testset_xsimple 0.0179998874664
1 overhead testset_simple 0.0190000534058
1 overhead testset_onecomma 0.0190000534058
1 overhead testset_complex 0.0190000534058
1 overhead testset_average 0.0309998989105
2 intcomma testset_xsimple 0.0360000133514
2 intcomma testset_simple 0.0369999408722
2 intcomma testset_onecomma 0.207999944687
2 intcomma testset_complex 0.302000045776
2 intcomma testset_average 0.523000001907
2 intcomma_noregex testset_xsimple 0.139999866486
2 intcomma_noregex testset_simple 0.141000032425
2 intcomma_noregex testset_onecomma 0.203999996185
2 intcomma_noregex testset_complex 0.200999975204
2 intcomma_noregex testset_average 0.523000001907
2 intcomma_noregex_reversed testset_xsimple 0.130000114441
2 intcomma_noregex_reversed testset_simple 0.129999876022
2 intcomma_noregex_reversed testset_onecomma 0.236000061035
2 intcomma_noregex_reversed testset_complex 0.241999864578
2 intcomma_noregex_reversed testset_average 0.582999944687
2 intcomma_recurs testset_xsimple 0.351000070572
2 intcomma_recurs testset_simple 0.352999925613
2 intcomma_recurs testset_onecomma 0.648999929428
2 intcomma_recurs testset_complex 0.808000087738
2 intcomma_recurs testset_average 1.81900000572
2 overhead testset_xsimple 0.0189998149872
2 overhead testset_simple 0.0189998149872
2 overhead testset_onecomma 0.0190000534058
2 overhead testset_complex 0.0179998874664
2 overhead testset_average 0.0299999713898
3 intcomma testset_xsimple 0.0360000133514
3 intcomma testset_simple 0.0360000133514
3 intcomma testset_onecomma 0.210000038147
3 intcomma testset_complex 0.305999994278
3 intcomma testset_average 0.493000030518
3 intcomma_noregex testset_xsimple 0.131999969482
3 intcomma_noregex testset_simple 0.136000156403
3 intcomma_noregex testset_onecomma 0.192999839783
3 intcomma_noregex testset_complex 0.202000141144
3 intcomma_noregex testset_average 0.509999990463
3 intcomma_noregex_reversed testset_xsimple 0.125999927521
3 intcomma_noregex_reversed testset_simple 0.126999855042
3 intcomma_noregex_reversed testset_onecomma 0.235999822617
3 intcomma_noregex_reversed testset_complex 0.243000030518
3 intcomma_noregex_reversed testset_average 0.56200003624
3 intcomma_recurs testset_xsimple 0.337000131607
3 intcomma_recurs testset_simple 0.342000007629
3 intcomma_recurs testset_onecomma 0.609999895096
3 intcomma_recurs testset_complex 0.75
3 intcomma_recurs testset_average 1.68300008774
3 overhead testset_xsimple 0.0189998149872
3 overhead testset_simple 0.018000125885
3 overhead testset_onecomma 0.018000125885
3 overhead testset_complex 0.0179998874664
3 overhead testset_average 0.0299999713898

Итальянские цифры:разделитель тысяч - это буква "а".'

Я решил это таким образом...для диктонария

from random import randint

voci = {
    "immobilizzazioni": randint(200000, 500000),
    "tfr": randint(10000, 25000),
    "ac": randint(150000, 200000),
    "fondo": randint(10500, 22350),
    "debiti": randint(150000, 250000),
    "ratei_attivi": randint(2000, 2500),
    "ratei_passivi": randint(1500, 2600),
    "crediti_v_soci": randint(10000, 30000)
}


testo_rnd2 = """Nell’azienda Hypermax S.p.a. di Bologna le immobilizzazioni valgono {immobilizzazioni:,} €, i debiti per TFR sono pari a {tfr:,} €, l’attivo circolante è di {ac:,} euro, il fondo rischi ed oneri ha un importo pari a {fondo:,} euro, i debiti sono {debiti:,} €, i ratei e risconti attivi sono pari a {ratei_attivi:,} euro, i ratei e risconti passivi sono pari a {ratei_passivi:,} euro. I crediti verso i soci sono pari a {crediti_v_soci:,} euro."""

print(testo_rnd2)

вон:le immobilizzazioni valgono 419.168 €.i debiti per TFR sono pari a 13.255 €.l’attivo circolante è di 195.443 euro.il fondo rischi ed oneri ha un importo pari a 13.374 euro.i debiti sono 180.947 €.i ratei e risconti attivi sono pari a 2.271 euro.i ratei e risconti passivi sono pari a 1.864 euro.I crediti verso i soci sono pari a 17.630 euro.

Вот еще один вариант, использующий функцию генератора, которая работает для целых чисел:

def ncomma(num):
    def _helper(num):
        # assert isinstance(numstr, basestring)
        numstr = '%d' % num
        for ii, digit in enumerate(reversed(numstr)):
            if ii and ii % 3 == 0 and digit.isdigit():
                yield ','
            yield digit

    return ''.join(reversed([n for n in _helper(num)]))

А вот и тест:

>>> for i in (0, 99, 999, 9999, 999999, 1000000, -1, -111, -1111, -111111, -1000000):
...     print i, ncomma(i)
... 
0 0
99 99
999 999
9999 9,999
999999 999,999
1000000 1,000,000
-1 -1
-111 -111
-1111 -1,111
-111111 -111,111
-1000000 -1,000,000

Просто подкласс long (или float, или как угодно). Это очень практично, потому что таким образом вы все равно можете использовать свои числа в математических операциях (и, следовательно, существующий код), но все они будут хорошо печататься в вашем терминале.

>>> class number(long):

        def __init__(self, value):
            self = value

        def __repr__(self):
            s = str(self)
            l = [x for x in s if x in '1234567890']
            for x in reversed(range(len(s)-1)[::3]):
                l.insert(-x, ',')
            l = ''.join(l[1:])
            return ('-'+l if self < 0 else l) 

>>> number(-100000)
-100,000
>>> number(-100)
-100
>>> number(-12345)
-12,345
>>> number(928374)
928,374
>>> 345

Для поплавков:

float(filter(lambda x: x!=',', '1,234.52'))
# returns 1234.52

Для целых:

int(filter(lambda x: x!=',', '1,234'))
# returns 1234

Если вы не хотите зависеть от каких-либо внешних библиотек:

 s = str(1234567)
 print ','.join([s[::-1][k:k+3][::-1] for k in xrange(len(s)-1, -1, -3)])

Это работает только для неотрицательных целых чисел.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top