% 格式化方法從 Python 剛開始的時候就存在了,堪稱「一屆元老」,可是 Python 官方文檔中並不推薦這種格式化方式:這裏描述的格式化操做容易表現出各類問題致使許多常見錯誤(例如沒法正確顯示元組和字典)。使用較新的格式化字符串文字或str.format()能夠有助於避免這些錯誤這些替代方案還提供了更強大,靈活和可打展的格式化文本方法。python
# 格式的字符串與被格式化的字符串必須一一對應,需格式化的字符串多時,容易搞混 print('hello %s, you sex is %s.' %('tab', 'boy')) # hello tab, you sex is boy. print('hello %s, you sex is %s.' %('boy', 'tab')) # hello boy, you sex is tab. # 經過字典方式格式化,哪一個字符將會格式化到哪裏,清晰命了 print('hello %(name)s, you sex is %(sex)s.' %{'name': 'tab', 'sex': 'boy'}) # hello tab, you sex is boy. args = {'name': 'tab', 'sex': 'boy'} print('hello %(name)s, you sex is %(sex)s.' %(args)) # hello tab, you sex is boy.
方式一:使用位置參數安全
In [62]: print('My name is {} ,age{}'.format('張亞飛',23)) My name is 張亞飛 ,age23 In [63]: print('My name is {0} ,age{1}'.format('張亞飛',23)) My name is 張亞飛 ,age23
方式二:用字典方式格式化時,指定格式化字符時的位置能夠調換函數
print('hello {name}, you sex is {sex}.'.format(sex='boy', name='tab')) # hello tab, you sex is boy.
# '**'起到解包的做用
args = {'name': 'tab', 'sex': 'boy'}
print('hello {name}, you sex is {sex}.'.format(**args))
方式三:填充與格式化spa
[填充字符][對齊方式 <^>][寬度]code
In [70]: print('{0:*<10}'.format('張亞飛')) 張亞飛******* In [71]: print('{0:*>10}'.format('張亞飛')) *******張亞飛 In [72]: print('{0:*^10}'.format('張亞飛')) ***張亞飛****
方式四:精度與進制orm
In [74]: print('{0:.2f}'.format(1232132.12321)) #精確到小數點後兩位 1232132.12 In [75]: print('{0:b}'.format(10)) #二進制 1010 In [76]: print('{0:o}'.format(10)) #十進制 12 In [77]: print('{0:x}'.format(10)) #十六進制 a In [78]: print('{0:,}'.format(123232244324)) #千分位格式化 123,232,244,324
方式五:使用索引blog
In [80]: l1 = ['張亞飛',23] In [85]: l2 = ['hobby','打籃球'] In [86]: print('{0[0]}age is {0[1]},{1[0]}is{1[1]}'.format(l1,l2)) 張亞飛age is 23,hobbyis打籃球
相比%格式化的方式, 推薦使用 .format 方法進行格式化字符串,一來清晰明瞭,二來效率更高(format 是字符串
str 內置的方法)。更多關於 .format 的用法文檔,用戶可在交互模式下(終端輸入 python
# or ipython or bpython ) 輸入 help(str.format) 查看索引
確實,str.format() 比 %格式化高級了一些,可是它仍是有本身的缺陷。ip
在處理多個參數和更長的字符串時仍然可能很是冗長。文檔
還好,如今咱們有了 f-Strings,它能夠使得字符串格式化更加容易。
f-string是以f或F開頭的字符串, 其中以{}包含的字符串會進行值替換
下面從多個方面看下 f-strings 的使用方法,看完後,我相信你會對「人生苦短,我用 Python」有更深地贊同~
name = 'ZhangYafei' age = 24 f'hi, {name}, are you {age}' Out[219]: 'hi, ZhangYafei, are you 24' F'hi, {name}, are you {age}' Out[220]: 'hi, ZhangYafei, are you 24'
由於 f-strings 是在運行時計算的,那麼這就意味着你能夠在其中放置任意合法的 Python 表達式,好比:
f'{2 ** 3 + 1}' Out[222]: '9'
還能夠調用函數:
def test(name): return name + ' really' f'{test(name)} is handsome' Out[231]: 'ZhangYafei really is handsome'
也能夠直接調用函數
f'{name.lower()} is handsome' Out[232]: 'zhangyafei is handsome'
class People(object): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f'{self.name} is {self.age}' def __repr__(self): return f'{self.name} is {self.age}. HAHA!' person = People() ZYF = People('ZhangYafei', 24) F'{ZYF}' Out[236]: 'ZhangYafei is 24' F'{ZYF!r}' Out[237]: 'ZhangYafei is 24. HAHA!' ZYF Out[238]: ZhangYafei is 24. HAHA! print(ZYF) ZhangYafei is 24
name = 'ZhangYafei' age = 24 status = 'Python' message = { f'hi {name}' f'you are {age}' f'you are learning {status}' } message Out[245]: {'hi ZhangYafeiyou are 24you are learning Python'}
這裏須要注意,每行都要加上 f 前綴,不然格式化會不起做用:
其實,f-string 裏的 f 也許能夠表明 fast,它比 %格式化方法和 str.format() 都要快:
from timeit import timeit def test_baifenhao(): name = 'ZhangYafei' age = 24 return '%s is %s.'%(name, age) def test_format(): name = 'ZhangYafei' age = 24 return '{} is {}.'.format(name, age) def test_f_string(): name = 'ZhangYafei' age = 24 return f'{name} is {age}.' timeit(test_baifenhao, number=1000000) Out[265]: 0.7293048258696899 timeit(test_format, number=1000000) Out[266]: 0.8064396247757486 timeit(test_f_string, number=1000000) Out[267]: 0.5187802432072317
5.1 引號的處理
能夠在字符串中使用各類引號,只要保證和外部的引號不重複便可。
如下使用方式都是沒問題的:
f"{'ZhangYafei'}" Out[268]: 'ZhangYafei' f'{"ZhangYafei"}' Out[269]: 'ZhangYafei' f"""ZhangYafei""" Out[270]: 'ZhangYafei' f'''ZhangYafei''' Out[271]: 'ZhangYafei'
那若是字符串內部的引號和外部的引號相同時呢?那就須要 進行轉義:
f'you are very \'handsome\'' Out[272]: "you are very 'handsome'"
5.2 括號的處理
若字符串中包含括號 {},那麼你就須要用雙括號包裹它:
f'{{100}}' Out[273]: '{100}' f'{{{100}}}' Out[275]: '{100}' f'{{{{100}}}}' Out[274]: '{{100}}' f'{{{{{100}}}}}' Out[276]: '{{100}}' f'{{{{{{100}}}}}}' Out[277]: '{{{100}}}'
5.3 反斜槓
上面說了,能夠用反斜槓進行轉義字符,可是不能在 f-string 表達式中使用:
5.4 註釋符號
不能在表達式中出現 #,不然會報出異常;
來看一個例子
from string import Template t = Template('Hey, $name!') t.substitute(name=name) Out[280]: 'Hey, ZhangYafei!'
你能夠看到咱們須要先從Python的內建 string 模塊中導入 Template 類。模板字符串並非核心的語言特徵,可是它們由Python標準庫的string提供的。
另一個不一樣的地方是這個模板字符串不支持使用格式說明符。因此想要讓先前的錯誤提示信息可以使用,你還須要手動轉換這個int 錯誤號碼爲十六進制字符串:
templ_string = 'Hey $name, there is a $error error!' Template(templ_string).substitute(name=name, error=hex(1111)) Out[282]: 'Hey ZhangYafei, there is a 0x457 error!'
順利運行!
可是該何時纔在你的代碼中使用模板字符串呢?在我看來,使用模板字符串的最佳的時機就是當你的程序須要處理由用戶提供的輸入內容時。模板字符串是最保險的選擇,由於能夠下降複雜性。
其餘一些複雜的字符串格式化技巧的可能會給你的程序帶來安全漏洞
Python字符串格式化經驗法則:若是你的格式化字符串是由用戶提供的,那麼就是用模板字符串(#4)避免安全問題。否則若是是Python 3.6+的話,就使用字符串插值/f-Strings,若是不是就使用「新式」字符串格式化(str.format)。
總結重點
● 也許感到驚訝,Python在處理字符串格式化時不僅有一種方法。
● 每一個方法都有其優缺點。你應該根據你的用例來選擇合適的方法
’