数字格式化属性¶
对数字的特定于区域设置的格式化和解析的支持由 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