相信很多人在格式化字串的時候都用"%s" % v
的語法,PEP 3101 提出一種更先進的格式化方法 str.format()
併成為 Python 3 的標準用來替換舊的 %s
格式化語法,CPython 從 2.6 開始已經實現了這一方法(其它直譯器未考證)。
format()
新的 format()
方法其實更像是一個簡略版的模板引起(Template Engine),功能非常豐富,官方文件對其語法的描述如下:
1 2 3 4 5 6 7 8 9 10 11 |
""" replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}" field_name ::= arg_name ("." attribute_name | "[" element_index "]")* arg_name ::= [identifier | integer] attribute_name ::= identifier element_index ::= integer | index_string index_string ::= + conversion ::= "r" | "s" | "a" format_spec ::= """ pass # Donot output |
我將其準換成鐵路圖的形式,(可能)更直觀一些:
模板中替換變數用 {}
包圍,且由 :
分為兩部分,其中後半部分 format_spec
在後面會單獨討論。前半部分有三種用法:
- 空
- 代表位置的數字
- 代表keyword的識別符號
這與函式呼叫的引數類別是一致的:
1 2 3 4 5 6 |
print("{} {}".format("Hello", "World")) # is equal to... print("{0} {1}".format("Hello", "World")) print("{hello} {world}".format(hello="Hello", world="World")) print("{0}{1}{0}".format("H", "e")) |
1 2 3 4 |
Hello World Hello World Hello World HeH |
除此之外,就像在0x05 函式引數與解包中提到的一樣,format()
中也可以直接使用解包操作:
1 2 |
print("{lang}.{suffix}".format(**{"lang": "Python", "suffix": "py"})) print("{} {}".format(*["Python", "Rocks"])) |
1 2 |
Python.py Python Rocks |
在模板中還可以通過 .identifier
和 [key]
的方式獲取變數內的屬性或值(需要注意的是 "{}{}"
相當於 "{0}{1}"
):
1 2 3 4 5 6 7 |
data = {'name': 'Python', 'score': 100} print("Name: {0[name]}, Score: {0[score]}".format(data)) # 不需要引號 langs = ["Python", "Ruby"] print("{0[0]} vs {0[1]}".format(langs)) print("n====nHelp(format):n {.__doc__}".format(str.format)) |
1 2 3 4 5 6 7 8 9 |
Name: Python, Score: 100 Python vs Ruby ==== Help(format): S.format(*args, **kwargs) -> str Return a formatted version of S, using substitutions from args and kwargs. The substitutions are identified by braces ('{' and '}'). |
強制轉換
可以通過 !
+ r|s|a
的方式對替換的變數進行強制轉換:
"{!r}"
對變數呼叫repr()
"{!s}"
對變數呼叫str()
"{!a}"
對變數呼叫ascii()
格式
最後 :
之後的部分定義輸出的樣式:
align
代表對齊方向,通常要配合 width
使用,而 fill
則是填充的字元(預設為空白):
1 2 3 4 |
for align, text in zip("", ["left", "center", "right"]): print("{:{fill}{align}16}".format(text, fill=align, align=align)) print("{:0=10}".format(100)) # = 只允許數字 |
1 2 |
left>>>>>>>>>>right 0000000100 |
同時可以看出,樣式設定裡面可以巢狀 {}
,但是必須通過 keyword 指定,且只能巢狀一層。
接下來是符號樣式:+|-|' '
分別指定數字是否需要強制符號(其中空格是指在正數的時候不顯示 +
但保留一位空格):
1 |
print("{0:+}n{1:-}n{0: }".format(3.14, -3.14)) |
1 2 3 |
+3.14 -3.14 3.14 |
#
用於表示特殊格式的數字(二進位制、十六進位制等)是否需要字首符號;,
也是用於表示數字時是否需要在千位處進行分隔;0
相當於前面的 {:0=}
右對齊並用 0
補充空位:
1 2 3 4 5 |
print("Binary: {0:b} => {0:#b}".format(3)) print("Large Number: {0:} => {0:,}".format(1.25e6)) print("Padding: {0:16} => {0:016}".format(3)) |
1 2 3 |
Binary: 11 => 0b11 Large Number: 1250000.0 => 1,250,000.0 Padding: 3 => 0000000000000003 |
最後兩個就是我們熟悉的小數點精度 .n
和格式化型別了,這裡僅給出一些示例,詳細內容可以查閱文件:
1 2 |
from math import pi print("pi = {pi:.2}, also = {pi:.7}".format(pi=pi)) |
1 |
pi = 3.1, also = 3.141593 |
Integer
1 2 |
for t in "b c d #o #x #X n".split(): print("Type {0:>2} of {1} shows: {1:{t}}".format(t, 97, t=t)) |
1 2 3 4 5 6 7 |
Type b of 97 shows: 1100001 Type c of 97 shows: a Type d of 97 shows: 97 Type #o of 97 shows: 0o141 Type #x of 97 shows: 0x61 Type #X of 97 shows: 0X61 Type n of 97 shows: 97 |
Float
1 2 |
for t, n in zip("eEfFgGn%", [12345, 12345, 1.3, 1.3, 1, 2, 3.14, 0.985]): print("Type {} shows: {:.2{t}}".format(t, n, t=t)) |
1 2 3 4 5 6 7 8 |
Type e shows: 1.23e+04 Type E shows: 1.23E+04 Type f shows: 1.30 Type F shows: 1.30 Type g shows: 1 Type G shows: 2 Type n shows: 3.1 Type % shows: 98.50% |
String (default)
1 2 3 4 |
try: print("{:s}".format(123)) except: print("{}".format(456)) |
1 |
456 |
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!