PEP 378 – 千位分隔符的格式說明符
- 作者:
- Raymond Hettinger <python at rcn.com>
- 狀態:
- 最終版
- 型別:
- 標準跟蹤
- 建立日期:
- 2009年3月12日
- Python 版本:
- 2.7, 3.1
- 釋出歷史:
- 2009年3月12日
動機
提供一種簡單、不依賴區域設定的方式來格式化帶千位分隔符的數字。
新增千位分隔符是使程式輸出人性化的最簡單方法之一,可以提高其專業外觀和可讀性。
在金融領域,帶千位分隔符的輸出是常態。金融使用者和非專業程式設計師認為區域設定方法令人沮喪、神秘且不明顯。
locale 模組還存在另外兩個挑戰。首先,它是一個全域性設定,不適用於需要以多種區域設定提供請求的多執行緒應用程式。其次,相關區域設定的名稱(例如“de_DE”)可能因平臺而異,或者可能根本未定義。locale 模組的文件詳細描述了這些以及許多其他挑戰。
目標不是取代 locale 模組、執行國際化任務或適應所有可能的約定。這些任務更適合像 Babel 這樣的健壯工具。相反,目標是讓許多使用者更容易完成常見的日常任務。
主要提案(來自 Alyssa Coghlan,最初稱為提案一)
將在 format() 說明符迷你語言中新增一個逗號
[[fill]align][sign][#][0][width][,][.precision][type]
',' 選項表示輸出中應包含逗號作為千位分隔符。與不使用句點作為小數點的區域設定一樣,使用不同數字分隔約定的區域設定將需要使用 locale 模組來獲得適當的格式。
該提案適用於浮點數、整數和 Decimal 型別。它還允許輕鬆替換其他分隔符。例如
format(n, "6,d").replace(",", "_")
這種技術完全通用,但在逗號和句點需要交換的情況下會很笨拙
format(n, "6,f").replace(",", "X").replace(".", ",").replace("X", ".")
寬度引數表示包括逗號和小數點在內的總長度
format(1234, "08,d") --> '0001,234'
format(1234.5, "08,.1f") --> '01,234.5'
',' 選項如上所示定義,適用於型別 'd'、'e'、'f'、'g'、'E'、'G'、'%' 和 'F'。為了允許將來的擴充套件,它對其他型別(二進位制、八進位制、十六進位制、字元等)是未定義的。
該提案的優點是比替代提案更簡單,但靈活性大大降低,開箱即用就能滿足的使用者需求更少。預計會為指定替代分隔符提供其他解決方案。
迷你語言的當前版本
- Python 2.6 文件
- PEP 3101 高階字串格式化
對其他語言做法的研究
瀏覽網頁,我發現千位分隔符通常是逗號、句點、空格、撇號或下劃線之一。
C-Sharp 提供了兩種樣式(圖片格式和型別說明符)。型別說明符方法是區域設定感知的。圖片格式只提供逗號作為千位分隔符
String.Format("{0:n}", 12400) ==> "12,400"
String.Format("{0:0,0}", 12400) ==> "12,400"
Common Lisp 在 ~D 十進位制型別說明符之前使用冒號來發出逗號作為千位分隔符。~D 的一般形式是 ~mincol,padchar,commachar,commaintervalD。padchar 預設為 SPACE。commachar 預設為 COMMA。commainterval 預設為三。
(format nil "~:D" 229345007) => "229,345,007"
- ADA 語言允許在其數字文字中使用下劃線。
Visual Basic 及其同類(例如 MS Excel)使用完全不同的樣式,並具有超靈活的自定義格式說明符,例如
"_($* #,##0_)".
COBOL 使用圖片子句,例如
PICTURE $***,**9.99CR
Java 提供了 Decimal.Format 類,它使用圖片模式(一個用於正數,一個可選用於負數),例如:"#,##0.00;(#,##0.00)"。它允許任意分組,包括百位和萬位,以及不均勻的分組。特殊模式字元是非本地化的(使用句點作為小數點分隔符,使用逗號作為分組分隔符)。使用者可以使用格式化程式的 DecimalFormatSymbols 物件提供一組替代符號。
替代提案(來自 Eric Smith,最初稱為提案二)
使千位分隔符和小數點分隔符都可由使用者指定,但不依賴於區域設定。為簡單起見,將選擇限制為逗號、句點、空格、撇號或下劃線。空格可以是 U+0020 或 U+00A0。
當分隔符後跟精度時,它是一個小數點分隔符,其前面的可選分隔符是一個千位分隔符。當精度不存在時,單獨的說明符表示千位分隔符
[[fill]align][sign][#][0][width][tsep][dsep precision][type]
示例
format(1234, "8.1f") --> ' 1234.0'
format(1234, "8,1f") --> ' 1234,0'
format(1234, "8.,1f") --> ' 1.234,0'
format(1234, "8 ,f") --> ' 1 234,0'
format(1234, "8d") --> ' 1234'
format(1234, "8,d") --> ' 1,234'
format(1234, "8_d") --> ' 1_234'
該提案滿足了大多數需求,但代價是需要付出更多的解析努力。並非所有可能的約定都涵蓋在內,但至少其中一個選項(空格或下劃線)對於來自各種背景的人們來說應該是可讀、可理解和有用的。
如示例所示,寬度引數表示包括千位分隔符和小數點分隔符在內的總長度。
對 locale 模組不作任何更改。
千位分隔符如上所示定義,適用於型別 'd'、'e'、'f'、'g'、'%'、'E'、'G' 和 'F'。為了允許將來的擴充套件,它對其他型別(二進位制、八進位制、十六進位制、字元等)是未定義的。
這個替代提案的缺點是很難在精神上解析單個分隔符是千位分隔符還是小數點分隔符。也許將小數點分隔符與精度說明符聯絡起來太神秘了。
評論
- 一些評論者根本不喜歡格式字串的想法,並認為它們難以閱讀。建議的替代方案包括 COBOL 樣式 PICTURE 方法或帶有關鍵字引數的便利函式,用於所有可能的組合。
- 一些新聞組回覆者認為,所有未國際化的指令碼都沒有立足之地,提供一種簡單的方式來硬編碼特定選擇是一種倒退(從而降低了使用區域設定敏感方法的動機)。
- 另一個想法是,在單個格式字串中嵌入一些特定約定會使以後更改該約定變得困難。沒有提出可行的替代方案,但一般想法是設定一次約定並使其到處適用(其他人評論說 locale 已經提供了這樣做的方法)。
- 對於浮點數小數部分的數字分組有一些先例,但本 PEP 不涉及該領域。只對小數點左側的數字進行分組。這不排除未來的擴充套件;它只是專注于格式化語言的一個單一、普遍有用的擴充套件。
- James Knight 觀察到印度/巴基斯坦的數字系統按百位分組。Ben Finney 指出中國按萬位分組。Eric Smith 指出這些已經由 locale 模組中的“n”說明符處理(儘管僅適用於整數)。本 PEP 不嘗試支援所有這些可能性。它專注於一種單一、相對常見的分組約定,它提供了一種快速方法來提高許多(儘管不是所有)上下文中的可讀性。
版權
本文件已置於公共領域。
來源:https://github.com/python/peps/blob/main/peps/pep-0378.rst
最後修改時間:2025-02-01 08:59:27 GMT