73個(gè)f-string的例子,幫你吃透字符串格式化
作者:Miguel Brito
原文:https://miguendes.me/73-examples-to-help-you-master-pythons-f-strings
翻譯:Python開(kāi)發(fā)者 /?felixGuo26
大家好,歡迎來(lái)到 Crossin的編程教室 !
本文將向你展示我認(rèn)為對(duì) Python?格式化字符串 f-string 來(lái)說(shuō)最重要的一些技巧。你會(huì)通過(guò)各種樣例學(xué)到多種格式化字符串的方法。總的來(lái)說(shuō),就是你會(huì)看到73個(gè)關(guān)于如何完美應(yīng)用 f-string 的例子。
?
目錄一覽
1. f-string 是什么?
2.?用 python 做基本的文本格式化
3. f-string?局限性
4.?如何格式化表達(dá)式
5.?如何使用f-string調(diào)試你的代碼
6.?如何在不同進(jìn)制下格式化數(shù)字
7.?如何使用格式化字符串常量打印出對(duì)象
8.?如何在格式化字符串常量中設(shè)置浮點(diǎn)數(shù)精度
9.?如何將數(shù)字格式化為百分比
10.?如何調(diào)整或者增加f-string的填充
11.?如何轉(zhuǎn)義字符
12.?如何使字符串居中
13.?如何添加千位分隔符
13.1如何使用逗號(hào)作為千分位分隔符格式化數(shù)字
13.2如何使用逗號(hào)作為小數(shù)分隔符格式化數(shù)字
14.如何用科學(xué)計(jì)數(shù)法(指數(shù)計(jì)數(shù)法)格式化數(shù)字
15.在?f-string?中使用?if-else
16.如何在 f-string 中使用字典
17.如何用 f-string?拼接字符串
18.如何格式化 datetime?對(duì)象
19.如何改正 f-string?的無(wú)效語(yǔ)法錯(cuò)誤
20.如何在字符串前補(bǔ)零
21.如何編寫(xiě)多行格式化字符串常量(怎樣應(yīng)對(duì)新行符號(hào))
22.總結(jié)
?
1、python 中的?f-string 是什么?
?
在 Python 的歷史中,字符串格式化的發(fā)展源遠(yuǎn)流長(zhǎng)。在?python 2.6 之前,想要格式化一個(gè)字符串,你只能使用?% 這個(gè)占位符,或者string.Template?模塊。不久之后,出現(xiàn)了更靈活更靠譜的字符串格式化方式: str.format 方法。
?
過(guò)去使用 %?做字符串格式化方式的代碼樣例:
>?msg?=?'hello?world'>?'msg:?%s'?%?msg'msg:?hello?world'
用string.format的樣例:
>?msg?=?'hello?world'>?'msg:?{}'.format(msg)'msg: hello world'
為了進(jìn)一步簡(jiǎn)化格式化方法,Eric Smith?在2015年提交了?PEP 498 -- Literal String Interpolation?提案。
PEP 498?提出了一種新的字符串插值方法,該方法可以更簡(jiǎn)單便捷的使用?str.format 方法。你只需要在字符串開(kāi)頭加上一個(gè)字母 f,形成 f”” 的格式就可以了。
?
使用f-string的樣例:
>?msg?=?'hello?world'>?f'msg:?{msg}''msg: hello world'
這就可以了!再也不需要用 string.format 或者 % 了。不過(guò) f-string?并不能完全替代 str.format。本文也將列舉出這兩者并不通用的情況。
?
2、基本的字符串格式化
如上文所述,使用f-string格式化字符串十分簡(jiǎn)單。唯一的要求就是給它一個(gè)有效的表達(dá)式。f-string?也可以用大寫(xiě)F開(kāi)頭或者與 r?原始字符串結(jié)合使用。但是你不能將其與?b”” 或者?”u”?混用。

?
book = "The dog guide"num_pages = 124f"The book {book} has{num_pages} pages"'The book The dog guide has 124 pages'F"The book {book} has{num_pages} pages"'The book The dog guide has 124 pages'print(Fr"The book {book} has{num_pages} pages\n")The?book?The?dog?guide?has?124?pages\n?>>>?print(FR"The?book?{book}?has{num_pages}?pages\n")The?book?The?dog?guide?has?124?pages\n>>>?print(f"The?book?{book}?has{num_pages}?pages\n")The?book?The?dog?guide?has?124?pages
差不多就這些!下一節(jié)中,我會(huì)用一些例子向你展示一些你用f-string能做或不能做的事兒。
?
3、f-string 的限制
雖然f-string十分的便捷,但它并不能完全代替str.format。f-string在表達(dá)式出現(xiàn)的上下文中進(jìn)行求值計(jì)算。根據(jù)PEP498,這意味著該表達(dá)式可以獲取所有局部和全局變量。而且該表達(dá)式是在運(yùn)行時(shí)計(jì)算的表達(dá)式。如果在?{
>?f"{name}"---------------------------------------------------------------------------NameError?????????????????????????????????Traceback(most?recent?call?last)1 -f0acc441190f>?in<module>----> 1 f"{name}"NameError: name 'name' is not defined
這對(duì) str.format 來(lái)說(shuō)就不是問(wèn)題,你可以提前定義一個(gè)模板字符串,并在之后調(diào)用.format方法時(shí)再傳遞上下文信息。
>?s?=?"{name}"> s.format(name="Python")'Python'> print(s){name}
另外還有個(gè)限制是,你不能在f-string中使用行內(nèi)注釋。
> f"My name is {name #name}!"File "" , line 1f"My name is {name #name}!"^SyntaxError: f-string expression part cannot include '#'
4、如何格式化一個(gè)表達(dá)式
如果不想定義變量,那你可以在大括號(hào)中使用常量。Python會(huì)計(jì)算該表達(dá)式并顯示最終計(jì)算結(jié)果。
>>>?f"4?*?4?is?{4?*?4}"'4 * 4 is 16'
或者你可以...
>?n?=?4>?f"4?*?4?is?{n?*?n}"'4 * 4 is 16'
?
5、如何使用?f-string?來(lái)調(diào)試代碼
調(diào)試是f-string最常見(jiàn)的用途之一了。Python3.8 之前,很多人會(huì)用一種非常繁雜的hello = 42; f"hello = {hello}”來(lái)進(jìn)行調(diào)試。針對(duì)此Python3.8引入了一個(gè)新功能。你可以用 f"{hello=}"?重寫(xiě)上面的代碼,而python會(huì)顯示hello=42。下面這個(gè)例子展示了在使用函數(shù)表達(dá)式時(shí)如何應(yīng)用該特性,其原理與上文代碼是一樣的。
def magic_number():...: return 42...:f"{magic_number() = }"'magic_number() = 42'
6、如何格式化數(shù)字的不同進(jìn)制

f-string 還能在不同進(jìn)制下顯示數(shù)字。例如,你不需要通過(guò)b來(lái)對(duì)一個(gè)int進(jìn)行格式轉(zhuǎn)化就可以顯示其二進(jìn)制結(jié)果。
>>>?f'{7:b}''111'
總結(jié)一下就是你可以用f-string來(lái)格式化:
???int?到二進(jìn)制
???int?到十六進(jìn)制
???int?到八進(jìn)制
???int?到十六進(jìn)制(所有符號(hào)大寫(xiě))
下面的例子使用縮進(jìn)功能和進(jìn)制格式化創(chuàng)建了一個(gè)表,可以顯示數(shù)字在不同進(jìn)制下的值。
bases = {"b": "bin","o": "oct","x": "hex","X": "HEX","d": "decimal"}for n in range(1, 21):...: for base, desc in bases.items():...: print(f"{n:5{base}}", end=' ')...: print()1 1 1 1 110 2 2 2 211 3 3 3 3100 4 4 4 4101 5 5 5 5110 6 6 6 6111 7 7 7 71000 10 8 8 81001 11 9 9 91010 12 a A 101011 13 b B 111100 14 c C 121101 15 d D 131110 16 e E 141111 17 f F 1510000 20 10 10 1610001 21 11 11 1710010 22 12 12 1810011 23 13 13 1910100 24 14 14 20
?
7、如何用?f-string 打印對(duì)象
你可以用f-string打印自定義對(duì)象。默認(rèn)設(shè)置是,如果你向f-string表達(dá)式傳遞了一個(gè)對(duì)象,它將會(huì)顯示該對(duì)象?__str__?方法的返回值。不過(guò),你也可以用顯式轉(zhuǎn)換操作標(biāo)志來(lái)打印__repr__的值。
!r - 使用?repr() 將值轉(zhuǎn)化為文本.
!s - 使用?str()?將值轉(zhuǎn)化為文本.
> class Color:def __init__(self, r: float = 255, g: float = 255, b: float = 255):self.r = rself.g = gself.b = bdef __str__(self) -> str:return "A RGB color"def __repr__(self) -> str:return f"Color(r={self.r}, g={self.g}, b={self.b})"> c = Color(r=123, g=32, b=255)#?如不加任何操作符,?會(huì)打印?__str__?的值>?f"{c}"'A?RGB?color'#?用`obj!r`?的話會(huì)打印?__repr__?的值>?f"{c!r}"'Color(r=123,?g=32,?b=255)'#?使用!s跟默認(rèn)值一樣>?f"{c!s}"'A RGB color'
Python也允許通過(guò)定義不同類(lèi)型使用__format__方法控制格式化結(jié)果,下面的例子會(huì)展示所有可能情況。
> class Color:def __init__(self, r: float = 255, g: float = 255, b: float = 255):self.r = rself.g = gself.b = bdef __str__(self) -> str:return "A RGB color"def __repr__(self) -> str:return f"Color(r={self.r}, g={self.g}, b={self.b})"> c = Color(r=123, g=32, b=255)# When no option is passed, the __str__ result is printed> f"{c}"'A RGB color'# When `obj!r` is used, the __repr__ output is printed> f"{c!r}"'Color(r=123, g=32, b=255)'# Same as the default> f"{c!s}"'A RGB color'Python also allows us to control the formatting on a per-type basis through the __format__ method. The following example shows how you can do all of that.> class Color:def __init__(self, r: float = 255, g: float = 255, b: float = 255):self.r = rself.g = gself.b = bdef __str__(self) -> str:return "A RGB color"def __repr__(self) -> str:return f"Color(r={self.r}, g={self.g}, b={self.b})"def __format__(self, format_spec: str) -> str:if not format_spec or format_spec == "s":return str(self)if format_spec == "r":return repr(self)if format_spec == "v":return f"Color(r={self.r}, g={self.g}, b={self.b}) - A nice RGB thing."if format_spec == "vv":return (f"Color(r={self.r}, g={self.g}, b={self.b}) "f"- A more verbose nice RGB thing.")if format_spec == "vvv":return (f"Color(r={self.r}, g={self.g}, b={self.b}) "f"- A SUPER verbose nice RGB thing.")raise ValueError(f"Unknown format code '{format_spec}' " "for object of type 'Color'")> c = Color(r=123, g=32, b=255)> f'{c:v}''Color(r=123, g=32, b=255) - A nice RGB thing.'> f'{c:vv}''Color(r=123, g=32, b=255) - A more verbose nice RGB thing.'> f'{c:vvv}''Color(r=123, g=32, b=255) - A SUPER verbose nice RGB thing.'> f'{c}''A RGB color'> f'{c:s}''A RGB color'> f'{c:r}''Color(r=123, g=32, b=255)'> f'{c:j}'---------------------------------------------------------------------------ValueError Traceback (most recent call last)20 -1c0ee8dd74be> in <module>----> 1 f'{c:j}'15 -985c4992e957> in __format__(self, format_spec)29 f"- A SUPER verbose nice RGB thing."30 )---> 31 raise ValueError(32 f"Unknown format code '{format_spec}' " "for object of type 'Color'"33 )ValueError: Unknown format code 'j' for object of type 'Color'
最后,還有個(gè)用來(lái)轉(zhuǎn)義ASCII字符的a操作符。更多信息可參考:
docs.python.org/3/library/functions.html#as..
?
>?utf_str?=?"áei?u">?f"{utf_str!a}""'\\xc1ei\\xf6u'"
?
8、如何用f-string設(shè)定浮點(diǎn)數(shù)精度
F-string可以像str.format那樣格式化浮點(diǎn)數(shù)。想要實(shí)現(xiàn)這一點(diǎn),你需要加一個(gè)?:(冒號(hào))再加一個(gè)?.(英文句號(hào))然后跟著小數(shù)點(diǎn)位數(shù)最后以f結(jié)尾。
舉例來(lái)說(shuō),你可以通過(guò)如下代碼打印一個(gè)浮點(diǎn)數(shù)精確到百分位的近似值。
>?num?=4.123956>?f"num?rounded?to?2?decimalpalces?=?{num:.2f}"'num rounded to 2 decimal palces = 4.12’
不加任何選項(xiàng)的話,則會(huì)打印浮點(diǎn)數(shù)本身的精確值。
>>>?print(f'{num}')4.123956
?
9、如何將一個(gè)數(shù)字格式化為百分?jǐn)?shù)
Python f-string方法有個(gè)非常便捷的實(shí)現(xiàn)格式化百分?jǐn)?shù)的操作方法。方法與浮點(diǎn)數(shù)格式化類(lèi)似,但是要用%代替結(jié)尾的f。它會(huì)將原始數(shù)值乘以100并顯示成有百分符號(hào)的固定格式。精度一樣也是可以設(shè)定的。
>?total?=?87> true_pos = 34> perc = true_pos / total> perc0.39080459770114945> f"Percentage of true positive: {perc:%}"'Percentage of true positive: 39.080460%'> f"Percentage of true positive: {perc:.2%}"'Percentage of true positive: 39.08%'
10、如何調(diào)整或者增加?f-string?的填充
?
你可以便捷的通過(guò)?< 或者 > 符號(hào)來(lái)調(diào)整字符串填充。

> greetings = "hello"> f"She says {greetings:>10}"'She says hello'# Pad 10 char to the right> f"{greetings:>10}"' hello'> f"{greetings:<10}"'hello '# You can omit the < for left padding> f"{greetings:10}"'hello '
?

a = "1"b = "21"c = "321"d = "4321"print("\n".join((f"{a:>10}", f"{b:>10}", f"{c:>10}", f"{d:>10}")))1213214321
?
11、如何轉(zhuǎn)義符號(hào)
如果你想想打印由大括號(hào)括起來(lái)的變量名稱(chēng),而不是該變量的值,那你需要雙層大括號(hào)?{{
>?hello?=?"world">f"{{hello}}?=?{hello}"'{hello}?=?world'
而如果你想轉(zhuǎn)義雙引號(hào),就需要在引號(hào)前用反斜線?\?做標(biāo)記。
>f"{hello} = \"hello\""'world?=?"hello"'
12、如何使字符串居中

想要實(shí)現(xiàn)字符串居中,可以通過(guò) var:^N 的方式。其中var是你想要打印的變量,N是字符串長(zhǎng)度。如果N小于var的長(zhǎng)度,會(huì)打印全部字符串。
> hello = "world">f"{hello:^11}"' world '>f"{hello:*^11}"'***world***'#?Extra?padding?is?added?to?the?right>f"{hello:*^10}"'**world***'#?N?shorter?than?len(hello)>f"{hello:^2}"'world'
13、如何格式化千分位
?

F-string也允許我們自定義數(shù)字顯示的格式。有個(gè)非常普遍的需求就是把數(shù)字以每3位為一個(gè)間隔使用下劃線進(jìn)行分隔。
> big_num = 1234567890>?f"{big_num:_}"'1_234_567_890'
?
13.1 ?如何使用逗號(hào)千分位分隔符數(shù)字
實(shí)際上,你可以隨便用任何符號(hào)做千分位分隔符。所以用逗號(hào)做分隔符也完全沒(méi)問(wèn)題。
> big_num = 1234567890>?f"{big_num:,}"'1,234,567,890'
?
甚至可以一次性同時(shí)搞定既有千分位分隔符又有精度設(shè)定的浮點(diǎn)數(shù)。
> num =2343552.6516251625>?f"{num:,.3f}"‘2,343,552.652'
13.2?如何用空格做千分位分隔符
用空格也可以嗎?
好吧,這個(gè)問(wèn)題是挺棘手,不過(guò)也能實(shí)現(xiàn)。你可以用逗號(hào)做分隔符之后再用空格替換逗號(hào)。
> big_num = 1234567890>?f"{big_num:,}".replace(',','?')'1?234?567?890'
還有個(gè)方法是設(shè)定你的本地語(yǔ)言環(huán)境,換成一個(gè)用空格作千位分隔符的環(huán)境比如pl_PL(波蘭語(yǔ)環(huán)境)。更多信息可參考這個(gè)Stack Overflow鏈接:
https://stackoverflow.com/a/17484665
?
14、如何用科學(xué)計(jì)數(shù)法(指數(shù)計(jì)數(shù)法)顯示一個(gè)數(shù)字
可以用 e 或者 E 字符來(lái)格式化。
> num =2343552.6516251625>f"{num:e}"'2.343553e+06'>?f"{num:E}"'2.343553E+06'>?f"{num:.2e}"'2.34e+06'>?f"{num:.4E}"'2.3436E+06'
?
15、在 f-string 中使用?if-else
F-string也能計(jì)算稍微復(fù)雜的運(yùn)算式,比如if/else
a = "this is a">>>?b?=?"this?is?b">>>?f"{a?if?10?>?5?else?b}"'this?is?a'>>>?f"{a?if?10?5?else?b}"'this?is?b'
?
16、如何在?f-string 中使用字典
你可以在f-string中使用字典。唯一的要求是引起整個(gè)字符串的引號(hào)要跟內(nèi)部的引號(hào)不一樣。
>color = {"R": 123, "G": 145, "B": 255}>?f"{color['R']}"'123'>?f'{color["R"]}'‘’123'此處有誤啊應(yīng)該是‘123’吧>>>?f"RGB?=?({color['R']},{color['G']},?{color['B']})"'RGB = (123, 145, 255)’
?
17、如何用?f-string 拼接字符串
合并f-string與普通字符串拼接一樣,可以隱式的直接拼接,或者顯式地用加號(hào) +,或者使用 str.join 方法。
# 隱式字符串拼接f"{123}" " = "f"{100}" " + " f"{20}" " + "f"{3}"'123?=?100?+?20?+?3'#?使用加號(hào)?+ 的顯式字符串拼接>>>?f"{12}"?+?"?!=?"+?f"{13}"'12?!=?13'#?使用str.join的字符串拼接>>>?"".join((f"{13}",?f"{45}"))'13 45'>>>"#".join((f"{13}", f"{45}"))'13#45'
?
18、如何格式化 datetime?對(duì)象
F-string也支持datetime對(duì)象的格式化。其過(guò)程與str.format格式化日期的方法很近似。請(qǐng)查閱官方文檔中的表格獲取更多所支持格式的相關(guān)信息。

> import datetime>?now?=?datetime.datetime.now()>?ten_days_ago?=?now?-datetime.timedelta(days=10)>?f'{ten_days_ago:%Y-%m-%d?%H:%M:%S}''2020-10-13 20:24:17'>?f'{now:%Y-%m-%d?%H:%M:%S}''2020-10-23?20:24:17'
19、如何修復(fù)f-string的非法格式錯(cuò)誤
如果用的不對(duì),f-string會(huì)報(bào)格式錯(cuò)誤。最常見(jiàn)的錯(cuò)誤就是雙引號(hào)里面套雙引號(hào)。單引號(hào)也會(huì)引發(fā)相同錯(cuò)誤。
>>>color = {"R": 123, "G": 145, "B": 255}>>>?f"{color["R"]}"File"" , line 1???f"{color["R"]}"???^SyntaxError:?f-string:?unmatched?'['>>>?f'{color['R']}'??File"" ,?line?1???f'{color['R']}'???^SyntaxError:?f-string:?unmatched?'['
?
?還有個(gè)常見(jiàn)錯(cuò)誤是在舊版本python中用f-string。python3.6才引入了f-string。如果你在之前版本中使用這個(gè)方法,解釋器會(huì)報(bào)格式錯(cuò)誤 SyntaxError: invalid syntax。
> f"this is an old version"?File"" ,?line?1???f"this?is?an?old?version"SyntaxError:?invalid?syntax
看到這個(gè)錯(cuò)誤的話,先確定當(dāng)前使用的python版本。我檢查的方法是在python2.7下通過(guò)調(diào)用sys.version來(lái)獲取版本號(hào)。
>>> import sys;print(sys.version)2.7.18?(default,?Apr?202020,?19:27:10)[GCC?8.3.0]
?
20、如何在字符串前補(bǔ)零
可以用{expr:0len}?這個(gè)方法來(lái)進(jìn)行字符串補(bǔ)零。len是最終返回字符串的長(zhǎng)度。還可以增加一個(gè)正負(fù)號(hào)標(biāo)記。在這種情況下,用+則無(wú)論數(shù)值為正負(fù)數(shù)都將顯示相應(yīng)正負(fù)號(hào)。用-則只有當(dāng)數(shù)值為負(fù)數(shù)時(shí)才顯示負(fù)號(hào),默認(rèn)設(shè)定也是如此。更多信息可參考該鏈接
https://docs.python.org/3/library/string.html#format-specification-mini-language
> num = 42>?f"{num:05}"'00042'>?f'{num:+010}''+000000042'>?f'{num:-010}''0000000042'>?f"{num:010}"'0000000042'>?num?=?-42>?f'{num:+010}''-000000042'>?f'{num:010}''-000000042'>?f'{num:-010}''-000000042'
?
21、如何處理多行f-string(換行符的處理)
?
你可以用換行符\n來(lái)打印多行文本。
multi_line = (f'R: {color["R"]}\nG: {color["G"]}\nB: {color["B"...: ]}\n')multi_line'R: 123\nG: 145\nB: 255\n'print(multi_line)R: 123G: 145B: 255
還可以用三引號(hào)實(shí)現(xiàn)多行字符串。這樣不單能增加換行符,還能有Tab。
>>>?other?=?f"""R:{color["R"]}????...:?G:{color["G"]}????...:?B:{color["B"]}????...:"""print(other)R:?123G:?145B: 255
用?Tab 的代碼樣例
>?other?=?f'''...:this is an example????...:????...:^Iof?color?{color["R"]}...:????...:?'''> other'\nthis is an example\n\n\tof color 123\n \n'>?print(other)this?is?an?example????of?color123>
22、結(jié)論
本文就這些!希望大家學(xué)到了一些新奇而實(shí)用的知識(shí)。知道了如何充分利用 f-string 絕對(duì)可以讓生活變得更美好。
_往期文章推薦_
