目錄
前面講的字符串都是靜態的,也就是說,一旦指定一個字符串,就固定不變了。但在很多場景下,需要替換字符串中的某一部分。當然,要實現這種操作最簡單的方式就是使用字符串連接,不過這太麻煩。在Python中爲了解決這個問題,提供了各種格式化字符串的方式。
所謂格式化字符串,其實就是在字符串中包含一些佔位符,然後用另外一些字符串來替換這些佔位符。本文將介紹Python中常用的字符串格式化方法。
1. 字符串格式化基礎
字符串格式化相當於字符串模板。也就是說,如果一個字符串有一部分是固定的,而另一部分是動態變化的,那麼就可以將固定的部分做成模板,然後那些動態變化的部分使用字符串格式化操作符(%)替換。如一句問候語:“Hello 李寧”,其中“Hello”是固定的,但“李寧”可能變成任何一個人的名字,如“喬布斯”,所以在這個字符串中,“Hello”是固定的部分,而“李寧”是動態變化的部分,因此,需要用“%”操作符替換“李寧”,這樣就形成了一個模板。
Hello %s
上面的代碼中,“%”後面的s是什麼呢?其實字符串格式化操作符後面需要跟着動態值的數據類型,以及更細節的格式(如對於浮點數來說,小數點後要保留幾位),這裏的“%s”表示動態部分要被替換成字符串類型的值。如果在字符串模板中有多個要被替換的部分,需要按順序用“%”表示,然後在格式化字符串時,傳入的值也要符合這個順序。下面的例子演示了格式化字符串的基本用法。
示例代碼:
# 定義字符串模板
formatStr = "Hello %s. Today is %s, Are there any activities today?"
# 初始化字符串格式化參數值,此處必須使用元組,不能使用列表
values = ('Mike', 'Wednesday')
# Hello Mike. Today is Wednesday, Are there any activities today?
print(formatStr % values) # 格式化字符串
基本的格式化字符串方法.py從上面的代碼可以看出,不僅在爲字符串模板指定格式化參數時要使用百分號(%),在格式化字符串時,也要像取模一樣使用“%”操作符。還有就是指定字符串格式化參數值要使用元組,在這裏不能使用列表。
在上面的例子中,只是使用了字符串作爲格式化參數,但在實際的應用中,可能會有其他類型的字符串格式化參數。如果遇到這種情況,可以使用str函數將這些數據類型的值轉換爲字符串類型的值,然後再傳入字符串模板,這麼做在大多數情況下是可行的,但如果要對格式化參數值有更進一步的要求,光使用str函數就做不到了,這就要使用能表示這些數據類型的格式化參數,如“%f”表示浮點類型的格式化參數。
示例代碼:用各種類型的值格式化字符串.py
# 在這個字符串模板中,包含了浮點數和整數類型的格式化參數
formatStr1 = "PI是圓周率,他的值是%.4f(保留小數點後%d位)"
# 導入math模塊中的pi變量
from math import pi
# 定義與formatStr1對應的格式化參數值
values1 = (pi, 4)
# 格式化字符串,運行結果:PI是圓周率,他的值是3.1416(保留小數點後4位)
# PI是圓周率,他的值是3.1416(保留小數點後4位)
print(formatStr1 % values1)
# 在這個字符串模板中,包含了整數和字符串類型的格式化參數
formatStr2 = "這件事的成功率是%d%%, 如果有%s參與的話,成功率會提升至%d%%"
values2 = (56, "John",70)
# 運行結果:這件事的成功率是56%, 如果有John參與的話,成功率會提升至70%
# 這件事的成功率是56%, 如果有John參與的話,成功率會提升至70%
print(formatStr2 % values2)
values3 = (66,"Mike")
# 由於指定的參數值的數量和格式化參數的數量不匹配,所以會拋出異常
# print(formatStr2 % values3)
在上面的代碼中,爲格式化字符串指定了不同數據類型的格式化參數。如果要在格式化字符串中顯示百分號(%),就要使用兩個百分號(%%)表示。當傳入的參數值的數量與格式化參數的數量不匹配時,就會拋出異常。
2. 模板字符串
在string模塊中提供了一個用於格式化字符串的Template類,該類的功能是用同一個值替換所有相同的格式化參數。Template類的格式化參數用美元符號($)開頭,後面跟着格式化參數名稱,相當於變量名。在格式化時,需要使用Template類的substitute方法,該方法用於指定格式化參數對應的值。
from string import Template
template = Template("$s $s $s ")
template.substitute(s = "Hello")
在上面的代碼中,通過Template類的構造方法傳入了一個格式化字符串,在這個格式化字符串中包含了3個“$s”,然後調用了substitute方法格式化這個字符串,該方法指定了s參數值爲“Hello”,最後的替換結果是“Hello Hello Hello”,也就是說,在格式化字符串中,有多少個“$s”,就替換多少個“$s”。substitute方法還可以通過字典(見下一章)設置格式化參數的值。下面的例子完整地演示瞭如何使用Template類格式化字符串。
示例代碼:模板字符串.py
# 引用string模塊中的Template類
from string import Template
template1 = Template("$s是我最喜歡的編程語言, $s非常容易學習,而且功能強大")
# 指定格式化參數s的值是Python
# Python是我最喜歡的編程語言, Python非常容易學習,而且功能強大
print(template1.substitute(s='Python'))
# 當格式化參數是一個字符串的一部分時,爲了和字符串的其他部分區分開,
# 需要用一對大括號將格式化參數變量括起來
template2 = Template("${s}stitute")
# substitute
print(template2.substitute(s='sub'))
template3 = Template("$dollar$$相當於多少$pounds")
# 替換兩個格式化參數變量
# 20$相當於多少英磅
print(template3.substitute(dollar=20, pounds='英磅'))
template4 = Template("$dollar$$相當於多少$pounds")
data = {}
data['dollar'] = 100
data['pounds'] = '英磅'
# 使用字典指定格式化參數值
# 100$相當於多少英磅
print(template4.substitute(data))
3. 字符串的format方法
字符串本身也有一個format方法用於格式化當前的字符串。這個format方法和前面講的格式化操作符(%)不太一樣。字符串格式化參數並不是用百分號(%)表示,而是用一對大括號({}),而且支持按順序指定格式化參數值和關鍵字格式化參數。例如,下面的代碼通過format方法按順序爲格式化字符串指定了參數值。
print("{} {} {}".format(1,2,3)) # 運行結果:1 2 3
我們可以看到,上面的代碼在字符串中指定了3對空的大括號,這代表3個格式化參數,不需要指定數據類型,可以向其傳遞Python語言支持的任何值。通過format方法傳入3個值(1,2,3),這3個值會按順序替換格式化字符串中的3對空的大括號。
命名格式化參數是指在一對大括號中指定一個名稱,然後調用format方法時也要指定這個名稱。
print("{a} {b} {c}".format(a = 1,c = 2,b = 3)) # 運行結果:1 3 2
上面的代碼在3對大括號中分別添加了“a”、“b”、“c”。通過format方法指定了這3個關鍵字參數的值。我們可以看到,並沒有按順序指定關鍵字參數的值。這也是使用關鍵字參數的好處,只要名字正確,fomat參數的順序可以任意指定。當然,順序方式和關鍵字參數方式可以混合使用,而且還可以指定順序方式中格式化參數從format方法提取參數值的順序,甚至可以取format方法參數值的一部分。哇,接連拋出了這麼多功能,可能很多讀者有點應接不暇了,彆着急,下面的例子爲我們演示format方法的一些常用使用方式。
示例代碼:format方法.py
# 包含了2個空的大括號,format方法需要按順序指定格式化參數值
s1 = "Today is {}, the temperature is {} degrees."
# format方法的第1個參數值對應s1的第1對大括號,第2個參數值對應s1的第2對大括號
# Today is Saturday, the temperature is 24 degrees.
print(s1.format("Saturday", 24))
# 包含了2個命名格式化參數,一個是{week},另一個是{degree}
s2 = "Today is {week}, the temperature is {degree} degrees."
# format方法的第1個參數指定了{degree}的值,第2個參數指定了{week}的值,
# 可以將degree和week調換,s2.format(week ="Sunday", degree = 22)
# Today is Sunday, the temperature is 22 degrees.
print(s2.format(degree=22, week="Sunday"))
# 混合了順序格式化參數和關鍵字格式化參數兩種方式
s3 = "Today is {week}, {},the {} temperature is {degree} degrees."
# format方法的參數,前面應該是按順序傳遞的格式化參數值,後面是關鍵字格式化參數值,順序不能調換
# 這樣做是錯誤的:s3.format(degree = 22, "aaaaa", 12345, week ="Sunday")
# Today is Sunday, aaaaa,the 12345 temperature is 22 degrees.
print(s3.format("aaaaa", 12345, degree=22, week="Sunday"))
# 爲順序格式化參數指定了從format方法獲取參數值的順序,{1}表示從format方法的第2個參數取值
# {0}表示從format方法的第1個參數取值
s4 = "Today is {week}, {1},the {0} temperature is {degree} degrees."
# Today is Sunday, 12345,the aaaaa temperature is 22 degrees.
print(s4.format("aaaaa", 12345, degree=22, week="Sunday"))
# 定義了一個列表
fullname = ["Bill", "Gates"]
# {name[1]}取fullname列表中的第2個值(Gates)
# format方法通過關鍵字參數,爲name名字指定了fullname列表。運行結果:Mr Gates
print("Mr {name[1]}".format(name=fullname))
# 導入math模塊
import math
# 訪問math模塊中的“__name__”變量來獲取模塊的名字,訪問math模塊中的pi變量獲取PI的值
s5 = "The {mod.__name__} module defines the value {mod.pi} for PI"
# format方法爲mod關鍵字參數指定了math模塊
# The math module defines the value 3.141592653589793 for PI
print(s5.format(mod=math))
4. 更進一步控制字符串格式化參數
format方法的功能遠不止這些,在一對大括號中添加一些字符串格式化類型符,可以對格式化字符串進行更多的控制。例如,下面的代碼會將一個字符串類型的格式化參數值按原樣輸出、通過repr函數輸出,以及輸出其Unicode編碼。
print("{first!s} {first!r} {first!a}".format(first = "中"))
執行這行代碼,會輸出如下的結果。
中 '中' '\u4e2d'
除此之外,format方法還支持很多其他的控制符,例如,可以將整數按浮點數輸出,也可以將十進制數按二進制、八進制、十六進制格式輸出。下面的例子爲我們演示瞭如何使用這些控制符格式化字符串。
示例代碼:控制符格式化字符串.py
# 原樣輸出:中 調用repr函數:'中' 輸出Unicode編碼:'\u4e2d'
print("原樣輸出:{first!s} 調用repr函數:{first!r} 輸出Unicode編碼:{first!a}".format(first = "中"))
# 將21按浮點數輸出
# 整數:21 浮點數:21.000000
print("整數:{num} 浮點數:{num:f}".format(num = 21))
# 將56按十進制、二進制、八進制和十六進制格式輸出
# 十進制:56 二進制:111000 八進制:70 十六進制:38
print("十進制:{num} 二進制:{num:b} 八進制:{num:o} 十六進制:{num:x}".format(num = 56))
# 將533按科學計數法格式輸出
# 科學計數法:5.330000e+02
print("科學計數法:{num:e}".format(num = 533))
# 將0.56按百分比格式輸出,運行結果:百分比:56.000000%
# 百分比:56.000000%
print("百分比:{num:%}".format(num = 0.56))
下圖是format支持的一些常用的字符串格式化類型符。