关于python:如何用逗号作为千位分隔符来输出数字?

How to print number with commas as thousands separators?

我尝试在python 2.6.1中用逗号作为千位分隔符打印一个整数。例如,我想将数字1234567显示为1,234,567。我该怎么做呢?我在谷歌上看到过很多例子,但我在寻找最简单实用的方法。

它不需要特定于区域设置来决定句点和逗号。我更喜欢尽可能简单的东西。


对于python≥2.7:

1
"{:,}".format(value)

根据格式规范,迷你语言,

The ',' option signals the use of a comma for a thousands separator. For a locale aware separator, use the 'n' integer presentation type instead.


我要用这个:

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

当然,您不需要国际化支持,但它清晰、简洁,并且使用内置库。

另外,"%d"是常用的%样式的格式化程序。您只能有一个格式化程序,但在字段宽度和精度设置方面,它可以是您需要的任何格式。

P.P.S.如果你不能让locale工作,我建议修改马克的答案:

1
2
3
4
5
6
7
8
9
10
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)

递归对于负数很有用,但对我来说,每个逗号一次递归似乎有点过分。


由于效率低下和不可读,很难击败:

1
2
3
>>> 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('-,','-')


以下是删除不相关部分并稍微清理后的区域设置分组代码:

(以下仅适用于整数)

1
2
3
4
5
6
7
8
9
10
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'

这里已经有了一些很好的答案。我只想添加这个以备将来参考。在Python2.7中,将有一个用于千位分隔符的格式说明符。根据python文档,它的工作方式是这样的

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

在python3.1中,您可以这样做:

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


我很惊讶没有人提到您可以用Python3.6中的F字符串这么简单地做到这一点:

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

…其中冒号后面的部分是格式说明符。逗号是所需的分隔符,因此f"{num:_d}"使用下划线而不是逗号。

这相当于对旧版本的python 3使用format(num,",d")


下面是一行regex的替代品:

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

仅适用于不等式输出:

1
2
3
4
5
6
7
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

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

注意:如果小数位数超过三位,则无法正常工作,因为它将尝试对小数部分进行分组:

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

它是如何工作的

让我们把它分解一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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:

1
2
3
my_number = 4385893.382939491

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

退货:4385893.38

更新:我最近有一个关于这种格式的问题(不能告诉你确切的原因),但通过删除0可以解决:

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


您还可以使用'{:n}'.format( value )来表示区域设置。我认为这是最简单的区域解决方案。

有关详细信息,请在python文档中搜索thousands

对于货币,可以使用locale.currency,设置标志grouping

代码

1
2
3
4
import locale

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

产量

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

我确信一定有一个标准的库函数来完成这个任务,但是尝试自己使用递归来编写它是很有趣的,所以我想到了以下几点:

1
2
3
4
5
6
7
8
9
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)

尽管如此,如果有人确实找到了一个标准的方法来做,你应该用它来代替。


稍微扩大了伊恩·施耐德的回答:

如果要使用自定义千位分隔符,最简单的解决方案是:

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

实例

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

如果您想要这样的德语表示,它会变得更加复杂:

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

从ActiveState配方498181的评论中,我修改了以下内容:

1
2
3
4
5
6
7
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),以确保只有三位数字组成的组在其后面有一个数字,才能得到逗号。我说"after",因为此时字符串是反向的。

[::-1]只是颠倒了一个字符串。


Python 3

——

整数(不带小数):

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

——

浮点数(带小数):

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

其中,f之前的数字指定小数位数。

——

奖金

印度Lakhs/Crores编号系统的快速脏启动功能(12,34567):

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


接受的答案是好的,但我实际上更喜欢format(number,',')。对我来说更容易理解和记忆。

https://docs.python.org/3/library/functions.html格式


从python 2.6版可以做到:

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

对于小于2.6的python版本,这里有两个手动解决方案,它们将浮点数转换为整数,但负数正确工作:

1
2
3
4
5
6
7
8
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)

这里没什么值得注意的:

  • 此行:string='%d'%number漂亮地将数字转换为字符串,它支持负数,并从浮点数中删除分数,使其变为整数;
  • 此切片索引[::-3]返回从开始的每三个项目最后,我用另一个切片[1]删除最后一个项目因为我不需要在最后一个数字后面加逗号;
  • 这是有条件的,如果我[索引]!="-"用于支持负数,不要在减号后插入逗号。

以及更硬核的版本:

1
2
3
4
5
6
7
8
9
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)


这里有一个也适用于浮动:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

使用实例:

1
2
3
4
5
6
>>> 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):

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

我是一个Python初学者,但是是一个经验丰富的程序员。我有python 3.5,所以我可以只使用逗号,但这仍然是一个有趣的编程练习。考虑无符号整数的情况。用于添加数千个分隔符的最可读的python程序似乎是:

1
2
3
4
5
6
7
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)

还可以使用列表理解:

1
2
3
4
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)

这是较短的,可能是一行,但你将不得不做一些心理体操,以了解为什么它的工作。在这两种情况下,我们得到:

1
2
3
for i in range(1, 11):
    instr = '1234567890'[:i]
    print(instr, add_commas(instr))
1
2
3
4
5
6
7
8
9
10
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

如果你想让程序被理解,第一个版本是更明智的选择。


只是long的子类(或float的子类,或其他)。这是非常实用的,因为这样您仍然可以在数学运算中使用您的数字(因此也可以使用现有代码),但它们都可以在您的终端中很好地打印出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> 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


我使用的是python 2.5,所以我无法访问内置格式。

我查看了django代码intcomma(intcomma在下面的代码中重复出现),发现它效率很低,因为它是递归的,并且在每次运行时编译regex也不是一件好事。这不是必要的"问题",因为Django并没有真正关注这种低级性能。另外,我期望在性能上有10倍的差别,但速度只慢了3倍。

出于好奇,我实现了intcomma的几个版本,以了解使用regex时的性能优势。我的测试数据得出的结论对这项任务有一点好处,但令人惊讶的是,这一点都不重要。

我也很高兴地看到了我所怀疑的:在no regex的情况下使用reverse xrange方法是不必要的,但它确实使代码看起来稍微好一些,代价是大约10%的性能。

另外,我假设您传递的是一个字符串,看起来有点像一个数字。结果未另行确定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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

测试结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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


这是和逗号一起做的钱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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代码不工作。我认为语法是不同的)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)

意大利数字:千位分隔符是一个''。

我是这样解决的…为一个独裁者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

出:不动产抵押贷款419.168欧元。每台TFR Sono Pari 13.255欧元。L'Attivo Circolante_di 195.443欧元。意大利方多Rischi Ed Oneri ha un importo pari 13.374欧元。我要180.947欧元。我认为这是2.271欧元。我认为Risconti Passivi Sono的汇率为1.864欧元。我相信法国社会保险公司17.630欧元。


根据PEP将其烘焙成python->https://www.python.org/dev/peps/pep-0378/

只需使用格式(1000,,

PEP中描述了更多的格式。


下面是另一个使用生成器函数的变量,该函数适用于整数:

1
2
3
4
5
6
7
8
9
10
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)]))

下面是一个测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 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


我更喜欢针对实际项目的基于区域设置的解决方案,但我认为这里应该提到使用切片分配的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def format_money(f, delimiter=',', frac_digits=2):

    negative_fix = int(f < 0)

    s = '%.*f' % (frac_digits, f)
    if len(s) < 5 + frac_digits + negative_fix:
        return s

    l = list(s)
    l_fix = l[negative_fix:]
    p = len(l_fix) - frac_digits - 5
    l_fix[p::-3] = [i + delimiter for i in l_fix[p::-3]]

    return ''.join(l[:negative_fix] + l_fix)

带doctests的gist在这里-https://gist.github.com/ei-grad/b290dc761ae253af69438bb94d82683


漂浮物:

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

适用于:

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


如果不想依赖任何外部库:

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

这只适用于非负整数。