使用.format()语法设置支持区域设置的字符串格式



是否有一种(通用(方法可以使用.format(){:}语法在Python中进行区域设置感知字符串格式化?我知道locale.format_string(),但它只接受旧的%语法。{:n}存在,但仅作为{:d}的替代品,不适用于其他格式。

我目前的方法如下,我预计这将在大多数非琐碎的情况下打破。

import locale
import string

class LocaleFormatter(string.Formatter):
def format_field(self, value, format_spec):
if format_spec[-1] not in 'eEfFgGdiouxXcrs':  # types copied from locale._percent_re
return super().format_field(value, format_spec)
grouping = ',' in format_spec or '_' in format_spec
format_spec = '%' + format_spec.replace(',', '').replace('_', '')
return locale.format_string(format_spec, value, grouping)

locale.setlocale(locale.LC_ALL, '')
fmt = LocaleFormatter()
fmt.format("Length: {:,.2f} mm, width: {:,.2f} mm", 1234.56, 7890)  # expected format is 1.234,56 for most locales

您可以实现将浮点转换为decimal、设置精度以及在需要时手动添加前导空格所需的功能:

import decimal
import locale
import re
import string
class LocaleFormatter(string.Formatter):
def format_field(self, value, format_spec):
if format_spec[-1] not in 'eEfFgGdiouxXcrs':  # types copied from locale._percent_re
return super().format_field(value, format_spec)
grouping = ',' in format_spec or '_' in format_spec
prec_re = re.match(r',?(?P<spec>(?P<width>d+)?(.(?P<precision>d+))?)?[eEfFgGdiouxXcrs]', format_spec)
if prec_re is not None and prec_re.group('spec') is not None:
space_len = prec_re.group('width')
after_dot = prec_re.group('precision')
if after_dot is not None:
pre_dot_value_len = len(str(int(value)))
ctx = decimal.Context(prec=int(after_dot) + pre_dot_value_len)
# prec turned out to be the length of the decimal repr, not precision
value = ctx.create_decimal(value)
if space_len is not None:
after_dot = 0 if after_dot is None else int(after_dot)
pre_dot = len(str(value))
how_many = pre_dot - after_dot - 1  # -1 for the dot character
if how_many > 0:
format_spec = how_many * ' ' + format_spec
format_spec = '%' + format_spec.replace(',', '').replace('_', '')
return locale.format_string(format_spec, value, grouping)
locale.setlocale(locale.LC_ALL, 'DE-DE')
fmt = LocaleFormatter()
res = fmt.format("Length: {:,.2f} mm, width: {:,2f} mm", 1234.567878, 7890)  # expected format is 1.234,56 for most locales
print(res)

结果是:

Length: 1.234,57 mm, width:         7.890,000000 mm

请注意,格式化后您建议的正确值没有正确舍入。上面的是

最新更新