数字格式化属性

对数字的特定于区域设置的格式化和解析的支持由 babel.numbers 模块:

>>> from babel.numbers import format_number, format_decimal, format_compact_decimal, format_percent

实例:

# Numbers with decimal places
>>> format_decimal(1.2345, locale='en_US')
u'1.234'
>>> format_decimal(1.2345, locale='sv_SE')
u'1,234'
# Integers with thousand grouping
>>> format_decimal(12345, locale='de_DE')
u'12.345'
>>> format_decimal(12345678, locale='de_DE')
u'12.345.678'

模式语法

虽然Babel使得为给定的区域设置使用适当的数字格式变得很简单,但是您也可以强制它使用自定义模式。与日期/时间格式设置模式一样,Babel支持的数字格式设置模式基于 Locale Data Markup Language specification (LDML)。

实例:

>>> format_decimal(-1.2345, format='#,##0.##;-#', locale='en')
u'-1.23'
>>> format_decimal(-1.2345, format='#,##0.##;(#)', locale='en')
u'(1.23)'

规范中详细介绍了自定义号码格式模式的语法。下表只是相对简要的概述。

符号

描述

0

数字

1-9

‘1’到‘9’表示四舍五入。

@

有效数字

#

数字,零表示不存在

.

小数分隔符或货币小数分隔符

-

减号

,

分组分隔符

E

在科学记数法中将尾数和指数分开

+

在正指数前加上本地化加号

;

分隔正子图案和负子图案

%

乘以100并显示为百分比

乘以1000并按毫秒显示

¤

货币符号,替换为货币符号。如果加倍,则替换为国际货币符号。如果是三倍数,则使用十进制符号的长形式。

'

用于引号前缀或后缀中的特殊字符

*

填充转义,位于填充字符之前

舍入模式

因为巴别塔充分利用了Python的 Decimal 类型在格式化前执行数字舍入,用户有机会通过活动控制舍入模式和其他可配置的参数 Context 实例。

默认情况下,Python取整模式为 ROUND_HALF_EVEN 它符合 UTS #35 section 3.3 。但是,调用者有机会在格式化数字或货币之前调整当前上下文:

>>> from babel.numbers import decimal, format_decimal
>>> with decimal.localcontext(decimal.Context(rounding=decimal.ROUND_DOWN)):
>>>    txt = format_decimal(123.99, format='#', locale='en_US')
>>> txt
u'123'

也可以使用 decimal.setcontext 或者直接修改 decimal.getcontext 。但是,由于自动恢复和嵌套它们的能力,使用上下文管理器总是更加方便。

无论选择哪种机制,始终使用 decimal 导入自的模块 babel.numbers 。出于效率原因,Babel使用可用的最快的十进制实现,例如 cdecimal 。这些不同实现提供了相同的API,但它们的类型和实例提供了相同的API not 相互之间进行互操作。

例如,可以稍微修改前面的示例以在Python2.7上生成意外结果,并使用 cdecimal 安装的模块:

>>> from decimal import localcontext, Context, ROUND_DOWN
>>> from babel.numbers import format_decimal
>>> with localcontext(Context(rounding=ROUND_DOWN)):
>>>    txt = format_decimal(123.99, format='#', locale='en_US')
>>> txt
u'124'

更改其他参数(如精度)也可能改变数字格式化函数的结果。请记住测试您的代码,以确保其行为符合预期。

解析数字

Babel还可以以区分区域设置的方式解析数字数据:

>>> from babel.numbers import parse_decimal, parse_number

实例:

>>> parse_decimal('1,099.98', locale='en_US')
1099.98
>>> parse_decimal('1.099,98', locale='de')
1099.98
>>> parse_decimal('2,109,998', locale='de')
Traceback (most recent call last):
  ...
NumberFormatError: '2,109,998' is not a valid decimal number

注意:从版本2.8.0开始, parse_number 函数的功能有限。它可以从数字字符串中删除某些区域设置的组符号,但在其逻辑处理更多编码问题和其他特殊情况之前,可能会出现意外行为。

实例:

>>> parse_number('1,099', locale='en_US')
1099
>>> parse_number('1.099.024', locale='de')
1099024
>>> parse_number('123' + u'\xa0' + '4567', locale='ru')
1234567
>>> parse_number('123 4567', locale='ru')
  ...
NumberFormatError: '123 4567' is not a valid number