Jak wydrukować liczbę przecinkami jako separatory tysięcy?

752

Próbuję wydrukować liczbę całkowitą w Pythonie 2.6.1 z przecinkami jako tysiące separatorów. Na przykład chcę pokazać numer 1234567jako 1,234,567. Jak miałbym to zrobić? Widziałem wiele przykładów w Google, ale szukam najprostszego praktycznego sposobu.

Aby wybierać między kropkami a przecinkami, nie musi być zależny od ustawień regionalnych. Wolałbym coś tak prostego, jak to możliwe.

Elias Zamaria
źródło

Odpowiedzi:

1737

Ustawienia regionalne są nieświadome

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

Świadome ustawienia regionalne

import locale
locale.setlocale(locale.LC_ALL, '')  # Use '' for auto, or force e.g. to 'en_US.UTF-8'

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

Odniesienie

Per specyfikacji formatu Mini-język ,

Ta ','opcja sygnalizuje użycie przecinka dla separatora tysięcy. W przypadku separatora rozpoznającego ustawienia narodowe użyj 'n'zamiast tego typu prezentacji liczby całkowitej.

Ian Schneider
źródło
24
Zauważ, że nie będzie to poprawne poza USA i kilkoma innymi miejscami, w takim przypadku wybrana locale.format () jest poprawną odpowiedzią.
Gringo Suave,
10
Forma argumentu słowa kluczowego:{val:,}.format(val=val)
CivFan,
11
Wielkie dzięki. W przypadku kwot pieniężnych z 2 miejscami po przecinku - „{:,. 2f}”. Format (wartość)
dlink
3
dla Portugalii, gdzie używamy punktu (.) jako separatora, po prostu: {:,} ". format (wartość) .replace (',', '.')
13
W Pythonie 3.6 i nowszych ciągi F zapewniają jeszcze większą wygodę. Np.f"{2 ** 64 - 1:,}"
CJ Gaconnet,
285

Mam to do pracy:

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

Jasne, nie potrzebujesz wsparcia na rzecz internacjonalizacji, ale jest przejrzysty, zwięzły i korzysta z wbudowanej biblioteki.

PS Ten „% d” jest zwykłym formatyzatorem w stylu%. Możesz mieć tylko jeden formatyzator, ale może to być wszystko, czego potrzebujesz pod względem ustawień szerokości i precyzji pola.

PPS Jeśli nie możesz dostać locale do pracy, proponuję zmodyfikowaną wersję odpowiedzi Marka:

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)

Rekurencja jest przydatna w przypadku negatywnym, ale jedna rekurencja na przecinek wydaje mi się nieco nadmierna.

Mike DeSimone
źródło
14
Próbowałem twojego kodu i niestety dostaję: „locale.Error: unupported locale setting”. : -s
Mark Byers
11
Mark: Jeśli korzystasz z Linuksa, możesz chcieć spojrzeć na to, co znajduje się w /etc/locale.gen, lub cokolwiek, czego używa twój glibc do budowania swoich ustawień narodowych. Możesz także spróbować użyć „” en ”,„ en_US.utf8 ”,„ en_US.UTF-8 ”,„ en_UK ”(sp?) Itp. Mikez: Potrzebna jest książka:„ Dr. PEP: Or Jak nauczyłem się przestać martwić i pokochać docs.python.org. ” Zrezygnowałem z zapamiętywania wszystkich bibliotek w Pythonie 1.5.6. Jeśli chodzi o to locale, używam tak mało, jak mogę.
Mike DeSimone
10
Możesz użyć „”, setlocaleaby użyć domyślnej, która, mam nadzieję, będzie odpowiednia.
Mark Ransom
24
Spróbuj tego: locale.setlocale (locale.LC_ALL, '') To zadziałało dla mnie
Nadia Alramli
1
Chociaż sprytne, nie lubię funkcji, które zmieniają ustawienia globalne ... Lepszym sposobem jest użycie „blah'.format ().
Cerin,
132

Trudno jest pokonać nieefektywność i nieczytelność:

>>> 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('-,','-')
Kasey Kirkham
źródło
171
Zagłosowano za najbardziej nieefektywną i nieczytelną metodą odpowiedzi na to pytanie.
psytek
1
byłoby miło, gdyby to przynajmniej działało. spróbuj tego numeru „17371830” staje się „173.718.3.0” =)
holms
5
Okresy? To nie jest nawet możliwe, holms. Ten kawałek śmieci całkowicie ignoruje ustawienia regionalne. Zastanawiam się, skąd masz ten wynik. Twój przykład produkuje dla mnie „17, 371 830”, zgodnie z oczekiwaniami.
Kasey Kirkham,
11
Aby uczynić to funkcją, sugerowałbym: lambda x: (lambda s: ','.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('-,','-'))(str(x))po prostu zachować motyw zaciemniający.
kwantowy
95

Oto kod grupujący ustawienia regionalne po usunięciu nieistotnych części i drobnym ich oczyszczeniu:

(Poniższe działa tylko dla liczb całkowitych)

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'

Tutaj jest już kilka dobrych odpowiedzi. Chcę tylko dodać to na przyszłość. W Pythonie 2.7 pojawi się specyfikator formatu dla separatora tysięcy. Według dokumentów Pythona działa to tak

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

W python3.1 możesz zrobić to samo:

>>> format(1234567, ',d')
'1,234,567'
Nadia Alramli
źródło
Tak, trudniejsze sposoby są głównie dla starszych użytkowników Pythona, takich jak te dostarczane z RHEL i innymi długoterminowymi dystrybucjami wsparcia.
Mike DeSimone
3
jak wyrazić to za pomocą ciągów formatu? „%, d”% 1234567 nie działa
Frederic Bazin
91

Dziwi mnie, że nikt nie wspomniał, że można to zrobić za pomocą f-stringów w Pythonie 3.6 tak łatwo:

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

... gdzie część po dwukropku jest specyfikatorem formatu. Przecinek to pożądany znak separatoraf"{num:_}" zamiast podkreślenia używa podkreślników.

Jest to równoważne z używaniem format(num, ",")dla starszych wersji Pythona 3.

Emil Stenström
źródło
39

Oto zamiennik wyrażenia regularnego w jednym wierszu:

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

Działa tylko w przypadku danych wyjściowych:

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'

Lub w przypadku liczb zmiennoprzecinkowych zawierających mniej niż 4 cyfry zmień specyfikator formatu na %.3f:

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

Uwaga: Nie działa poprawnie z więcej niż trzema cyframi dziesiętnymi, ponieważ będzie próbował zgrupować część dziesiętną:

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

Jak to działa

Rozbijmy to:

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
Daniel Fortunov
źródło
1
użyj trybu
pełnego,
Czy nie możesz zamienić „(?! \ D)” na „$”?
GL2014
28

To właśnie robię dla pływaków. Chociaż, szczerze mówiąc, nie jestem pewien, dla których wersji to działa - używam 2.7:

my_number = 4385893.382939491

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

Zwraca: 4 385 893,38

Aktualizacja: Niedawno miałem problem z tym formatem (nie mogłem podać dokładnego powodu), ale mogłem go naprawić, upuszczając 0:

my_string = '{:,.2f}'.format(my_number)
elPastor
źródło
19

Możesz także użyć '{:n}'.format( value )do reprezentacji ustawień regionalnych. Myślę, że to najprostszy sposób na rozwiązanie regionalne.

Aby uzyskać więcej informacji, wyszukaj thousandsw Python DOC .

W przypadku waluty możesz użyć locale.currency, ustawiając flagę grouping:

Kod

import locale

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

Wynik

'Portuguese_Brazil.1252'
'R$ 1.234.567,89'
DiogoLR
źródło
13

Nieznacznie rozszerzając odpowiedź Iana Schneidera:

Jeśli chcesz użyć niestandardowego separatora tysięcy, najprostszym rozwiązaniem jest:

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

Przykłady

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

Jeśli chcesz taką reprezentację Niemiec, staje się ona nieco bardziej skomplikowana:

('{:,.2f}'.format(123456789.012345)
          .replace(',', ' ')  # 'save' the thousands separators 
          .replace('.', ',')  # dot to comma
          .replace(' ', '.')) # thousand separators to dot
Martin Thoma
źródło
Nieco krótszy:'{:_.2f}'.format(12345.6789).replace('.', ',').replace('_', '.')
Tom Pohl
12

Jestem pewien, że musi istnieć standardowa funkcja biblioteki, ale fajnie było spróbować napisać ją samemu za pomocą rekurencji, więc oto, co wymyśliłem:

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)

Powiedziawszy to, jeśli ktoś inny znajdzie standardowy sposób na zrobienie tego, powinieneś go użyć.

Mark Byers
źródło
Niestety nie działa we wszystkich przypadkach. intToStringWithCommas (1000.1) -> „1.0001,000”
Nadia Alramli
W szczególności powiedział liczby całkowite i że powinno to być tak proste, jak to możliwe, więc postanowiłem nie obsługiwać typów danych innych niż liczby całkowite. Podałem to również wyraźnie w nazwie funkcji _int_ToStringWithCommas. Teraz dodałem także podwyżkę, aby była bardziej przejrzysta.
Mark Byers,
8

Od komentarzy do przepisu activestate 498181 Przerobiłem to:

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

Wykorzystuje funkcję wyrażeń regularnych: lookahead, tj. (?=\d)Aby upewnić się, że tylko grupy trzech cyfr, które mają cyfrę „po”, otrzymają przecinek. Mówię „po”, ponieważ w tym momencie ciąg znaków jest odwrotny.

[::-1] po prostu odwraca ciąg.

Tom Viner
źródło
8

Przyjęta odpowiedź jest w porządku, ale tak naprawdę wolę format(number,','). Łatwiej jest mi interpretować i pamiętać.

https://docs.python.org/3/library/functions.html#format

Magenta Nova
źródło
Działa idealnie, unikając wyświetlania zbyt wielu cyfr dziesiętnych dla liczb zmiennoprzecinkowych.
Rexcirus
7

Python 3

-

Liczby całkowite (bez miejsc dziesiętnych):

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

-

Liczba zmiennoprzecinkowa (z przecinkiem):

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

gdzie liczba poprzednia fokreśla liczbę miejsc dziesiętnych.

-

Premia

Szybka i brudna funkcja startowa dla indyjskiego systemu numeracji lakhs / crores (12 34567):

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

Adam Starrh
źródło
5

od wersji Python 2.6 możesz to zrobić:

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

Dla wersji Pythona <2.6 i tylko dla twojej informacji, oto 2 ręczne rozwiązania, zmieniają liczby zmiennoprzecinkowe na liczby całkowite, ale liczby ujemne działają poprawnie:

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)

kilka rzeczy do zauważenia tutaj:

  • ta linia: string = '% d'% number pięknie konwertuje liczbę na ciąg, obsługuje negatywy i upuszcza ułamki zwykłe, czyniąc je intami;
  • ten wycinek indeksuje [:: - 3] zwraca co trzeci element, zaczynając od końca, więc użyłem innego wycinka [1:], aby usunąć ostatni element, ponieważ nie potrzebuję przecinka po ostatnim numerze;
  • jest to warunek, jeśli l [indeks]! = '-' jest używany do obsługi liczb ujemnych, nie wstawiaj przecinka po znaku minus.

I bardziej hardkorowa wersja:

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)
arka
źródło
2

Jestem początkującym w Pythonie, ale doświadczonym programistą. Mam Python 3.5, więc mogę po prostu użyć przecinka, ale jest to jednak interesujące ćwiczenie programistyczne. Rozważ przypadek liczby całkowitej bez znaku. Najbardziej czytelnym programem do dodawania tysięcy separatorów w języku Python jest:

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)

Możliwe jest również użycie listowego zrozumienia:

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)

To jest krótsze i może być jedno-liniowe, ale będziesz musiał zrobić gimnastykę umysłową, aby zrozumieć, dlaczego to działa. W obu przypadkach otrzymujemy:

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

Pierwsza wersja jest bardziej rozsądnym wyborem, jeśli chcesz, aby program był zrozumiały.

Geoff Fergusson
źródło
1

Oto jeden, który działa również dla pływaków:

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

Przykład użycia:

>>> float2comma(10000.1111)
'10,000.111,1'
>>> float2comma(656565.122)
'656,565.122'
>>> float2comma(-656565.122)
'-656,565.122'
Edward van Kuik
źródło
1
float2comma(12031023.1323)zwraca: '12, 031,023.132,3 '
demultipleksacja
1

Jedna linijka dla Python 2.5+ i Python 3 (tylko dodatnie int):

''.join(reversed([x + (',' if i and not i % 3 else '') for i, x in enumerate(reversed(str(1234567)))]))
Collin Anderson
źródło
1

Uniwersalne rozwiązanie

Znalazłem pewne problemy z separatorem kropek w poprzednich najczęściej głosowanych odpowiedziach. Zaprojektowałem uniwersalne rozwiązanie, w którym możesz użyć, co chcesz, jako separatora tysięcy bez modyfikowania ustawień regionalnych . Wiem, że to nie jest najbardziej eleganckie rozwiązanie, ale wykonuje zadanie. Możesz to poprawić!

def format_integer(number, thousand_separator='.'):
    def reverse(string):
        string = "".join(reversed(string))
        return string

    s = reverse(str(number))
    count = 0
    result = ''
    for char in s:
        count = count + 1
        if count % 3 == 0:
            if len(s) == count:
                result = char + result
            else:
                result = thousand_separator + char + result
        else:
            result = char + result
    return result


print(format_integer(50))
# 50
print(format_integer(500))
# 500
print(format_integer(50000))
# 50.000
print(format_integer(50000000))
# 50.000.000
Manrique
źródło
0

To robi pieniądze wraz z przecinkami

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)
Bob F.
źródło
0

Mam wersję tego kodu w języku Python 2 i Python 3. Wiem, że pytanie zostało zadane dla Pythona 2, ale teraz (8 lat później) ludzie prawdopodobnie będą używać Pythona 3.

Kod 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))        


Kod Python 2: (Edytuj. Kod Python 2 nie działa. Myślę, że składnia jest inna).

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) 
Dinozaur212
źródło
0

Używam Pythona 2.5, więc nie mam dostępu do wbudowanego formatowania.

Spojrzałem na kod Django intcomma (intcomma_recurs w kodzie poniżej) i zdałem sobie sprawę, że jest nieefektywny, ponieważ jest rekurencyjny, a także kompilacja wyrażenia regularnego przy każdym uruchomieniu również nie jest dobrą rzeczą. Nie jest to konieczny „problem”, ponieważ django tak naprawdę nie koncentruje się na tego rodzaju wydajności na niskim poziomie. Spodziewałem się też 10-krotnej różnicy w wydajności, ale jest ona tylko 3-krotnie wolniejsza.

Z ciekawości zaimplementowałem kilka wersji intcomma, aby zobaczyć, jakie są zalety wydajności podczas używania wyrażenia regularnego. Moje dane testowe wskazują na niewielką zaletę tego zadania, ale zaskakująco niewiele.

Z przyjemnością zobaczyłem również to, co podejrzewałem: stosowanie odwrotnego zakresu xrange jest niepotrzebne w przypadku braku wyrażenia regularnego, ale sprawia, że ​​kod wygląda nieco lepiej kosztem ~ 10% wydajności.

Zakładam też, że to, co przekazujesz, to ciąg znaków i wygląda trochę jak liczba. Wyniki nie zostały określone inaczej.

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

A oto wyniki testu:

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
parzystość 3
źródło
Myślałem, że jedno-regexowe rozwiązanie Daniela Fortunova będzie nr 1 i pobije wszystkie algorytmy, ponieważ regex jest tak dopracowany / zoptymalizowany i zakodowany w C, ale nie ... Myślę, że wzorzec i oczekiwania są zbyt drogie. wpada około dwa razy szybciej niż intcomma powyżej, nawet przy prekompilacji wyrażenia regularnego.
parzystość3
0

jest to zapieczętowane w Pythonie na PEP -> https://www.python.org/dev/peps/pep-0378/

wystarczy użyć formatu (1000, ', d'), aby wyświetlić liczbę całkowitą z separatorem tysięcy

istnieje więcej formatów opisanych w PEP, miej na to

Raveen Beemsingh
źródło
-1

Oto inny wariant wykorzystujący funkcję generatora, która działa dla liczb całkowitych:

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)]))

A oto test:

>>> 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
użytkownik650654
źródło
-1

Po prostu podklasa long( floatlub cokolwiek innego). Jest to bardzo praktyczne, ponieważ w ten sposób nadal możesz używać swoich liczb w operacjach matematycznych (a zatem i istniejącym kodzie), ale wszystkie będą ładnie drukować w twoim terminalu.

>>> 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
twneale
źródło
8
Podoba mi się pomysł na podklasę, ale czy jest __repr__()poprawna metoda zastąpienia? Sugerowałbym zastąpienie __str__()i pozostawienie w __repr__()spokoju, ponieważ int(repr(number(928374)))powinien działać, ale int()będzie się dusił przecinkami.
steveha,
@steveha ma rację, ale uzasadnienie powinno być takie, że number(repr(number(928374)))nie działa, nie int(repr(number(928374))). Niemniej jednak, aby to podejście działało bezpośrednio print, zgodnie z żądaniem PO, __str__()metoda powinna być zastąpiona __repr__(). Niezależnie od tego wydaje się, że w logice wstawiania przecinka występuje błąd.
martineau
-1

Włochy:

>>> import locale
>>> locale.setlocale(locale.LC_ALL,"")
'Italian_Italy.1252'
>>> f"{1000:n}"
'1.000'
Giovanni G. PY
źródło
-8

Dla pływaków:

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

Dla ints:

int(filter(lambda x: x!=',', '1,234'))
# returns 1234
Jennifer
źródło
5
To usuwa przecinki. Choć przydatny, PO poprosił o sposób ich dodania . Poza tym coś takiego float('1,234.52'.translate(None, ','))może być prostsze i być może szybsze.
Wstrzymano do odwołania.