0 - 占位符介紹
要實現字符串的拼接,使用占位符是的一種高效、常用的方式。
舉個例子,下面是不使用占位符的一種寫法,直接使用加號拼接字符串
name = "Li hua"
age = 24
print("Hello "+name+", you are " + str(age) + " years old")
換成使用占位符的,可以寫為
name = "Li hua"
age = 24
print("Hello %s, you are %d years old" % (name, age))
其中%s
、%d
便是占位符,顧名思義,其作用就是替后面的變量站住這個位置,
字符串后面的%是一個特殊的操作符,該操作符會將后面的變量值,替換掉前面字符串中的占位符。
對比兩種寫法,會發現使用占位符可以
- 將字符串中用到變量集中在一起,方便查找和修改
- 避免了反復使用引號,導致的引號對應識別困難
- 能夠更直接通順的看出句子的內容
實際上,占位符的優點還有很多,具體可以在下面的使用中去體會。
目前常用的占位符寫法有三種
- %
- format
- f表達式
每種方法下,占位符的寫法和意思又有不同。
下面依次介紹下這三種並給出幾個使用示例。
1 - %
參考文獻:
% (String Formatting Operator)
printf-style-string-formatting
上文已介紹過,%
是一個特殊的操作符,該操作符會將后面的變量值,替換掉前面字符串中的占位符。
其詳細語法格式如下:
"... %[key][flags][width][.precision][length type]conversion type ..." % values
其中
%[key][flags][width][.precision][length type]conversion type
是該方法下,占位符詳細語法的格式。
依次介紹下上面占位符每個符號每個字段的意思
%
: 必須要有的符號。它標記占位符的開始。key
: 選填。映射的鍵,由帶括號的字符序列組成,一般用於后面的values是是字典的場景。flags
: 選填。轉換標志(Conversion flags), 會影響某些轉換類型的結果。width
: 選填。最小字段寬度。如果指定為“*”(星號),則實際寬度從值中元組的下一個元素讀取,要轉換的對象位於最小字段寬度和可選精度之后。precision
: 選填。精度,寫法為.precision
(點+精度)。如果指定為“*”(星號),則實際寬度從值中元組的下一個元素讀取,要轉換的值位於精度之后。length type
: 選填。長度修改器。Conversion type
: 必須要有的符號。轉換類型,也標記占位符的開始。
下面依次使用一個小示例展示下上面每個字段的用法
Conversion type
由於這個字段是必選字段,所以最先介紹(%
寫法是固定的,Conversion type
則必須要選擇一個轉換類型)
類型有很多,只介紹三個非常常用的,(更多的建議查閱官方文檔:printf-style-string-formatting)
Conversion type |
說明 |
---|---|
s |
字符串(使用str() 方法轉換任何Python對象) |
d |
十進制整數 |
f |
十進制浮點數(小數), 自動保留六位小數。 |
示例:
>>> "%s %s %s" % ("hello", 3, 3.1415)
'hello 3 3.1415'
>>> "%s %d %d" % ("hello", 3, 3.1415)
'hello 3 3'
>>> "%s %d %f" % ("hello", 3, 3.1415)
'hello 3 3.141500'
>>> "%s %f %f" % ("hello", 3, 3.1415)
'hello 3.000000 3.141500'
觀察上面的示例,不難看出s
是一個非常通用的類型,所以很多不講究的場景,Conversion type
我通通都用s
。
precision
對於有小數的場景,設置精度是基本操作。
其寫法為.precision
(點+精度)。
不設置的話,浮點數默認精度值是6。
示例如下
>>> '%f' % 3.14
'3.140000'
>>> '%.1f' % 3.14
'3.1'
>>> '%.2f' % 3.14
'3.14'
>>> '%.3f' % 3.14
'3.140'
>>> '%.4f' % 3.14
'3.1400'
一般來說,%
操作符下占位符了解到這里就夠了,下面的是比較少用的生僻內容。而且也不實用,復雜的對齊操作推薦使用format
或f
表達式。
key
(不常用)
這個選填字段是搭配字典格式的values
使用的
示例如下
>>> "%(name)s %(age)s" % {"name": "Lihua", "age": 20}
'Lihua 20'
>>> "%(name)s %(age)s" % ({"name": "Lihua", "age": 20})
'Lihua 20'
>>> "%(0)s %(1)s" % ("Lihua", 20)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: format requires a mapping
flags
(不常用)
該類型可選擇的值有:#
、0
、-
、
、+
;
這里只介紹其中幾種,(更多的建議查閱官方文檔:printf-style-string-formatting)
flags |
說明 |
---|---|
0 |
數值的轉換將被零填充,需搭配width 使用(示例見下面的width 中的)。 |
- |
轉化結果左對齊,需搭配width 使用(示例見下面的width 中的), 該標志符會覆蓋0 標志符。 |
|
空格, 在帶符號的轉換產生的正數(或空字符串), 之前留一個空格(方便正負數最后對齊)。 |
+ |
轉換數字后,數字前面將會展示其正負號(“+”或“-”), 該標志符會覆蓋 標志符。 |
示例如下
>>> "% d %+d" % (1234, 1234)
' 1234 +1234'
>>> "% d %+d" % (-1234, -1234)
'-1234 -1234'
width
設置字段的最小占位寬度,默認右對齊,內容不夠時使用空格填充。
>>> "%4d,%6d,%10f" % (12, 1234, 3.14)
' 12, 1234, 3.140000'
>>> "%04d,%06d,%010f" % (12, 1234, 3.14) # use '0' flag
'0012,001234,003.140000'
>>> "%-4d,%-6d,%-10f" % (12, 1234, 3.14) # use '-' flag
'12 ,1234 ,3.140000 '
>>> "%0-4d,%0-6d,%0-10f" % (12, 1234, 3.14) # '-' flag will override '0' flag
'12 ,1234 ,3.140000 '
length type
(使用方式未知)
2 - format
參考文獻:https://docs.python.org/3.6/library/string.html#format-string-syntax
注意:該方法,在python2和3中的語法有些細微的差異,這里介紹python3.6版本的(應該python3都差不多),具體區別查閱對應版本的官方文檔。
str.format()
是Python2.6開始的新功能,是字符串格式化方法之一,它允許多個替換、值格式化。
這個方法允許我們通過位置,格式化連接字符串中的元素。
這個方法是一個非常實用且強大的方法。
對於復雜的對齊要求,首選該方法。
其總的語法格式如下
"... {[field_name][!conversion][:format_spec]} ...".format(arguments)
arguments
首先介紹下arguments
,其有兩種情況:
- 位置參數(Positional Arguments)
>>> "{} {}".format("Li hua", 24)
'Li hua 24'
>>> "{0} {1} {1} {0}".format("Li hua", 24)
'Li hua 24 24 Li hua'
>>> "{} {} {} {}".format("Li hua", 24)
Traceback (most recent call last):
File "<input>", line 1, in <module>
IndexError: tuple index out of range
- 關鍵字參數(Keyword Arguments)
>>> "{name} {age}".format(name="Li hua", age=24)
'Li hua 24'
>>> "{name} {age} {age} {name}".format("Li hua", 24)
'Li hua 24 24 Li hua'
>>> "{} {}".format(name="Li hua", age=24)
Traceback (most recent call last):
File "<input>", line 1, in <module>
IndexError: tuple index out of range
補充:其實位置參數和關鍵字參數可以混用,但是不推薦
然后介紹下該語法下的占位符格式:
{[field_name][!conversion][:format_spec]}
field_name
: 選填。字段名,常使用其基礎格式arg_name
來指定使用arguments
哪一個。
對於關鍵詞參數,arg_name
必須為其中的關鍵字,(此時該字段是必填項)
比如"{name} {age}".format(name="Li hua", age=24)
對於位置參數,arg_name
必須為序號,(此時該字段可不填,不填則默認第一個為0,從前往后依次+1)
比如"{0} {1}".format("Li hua", 24)
,"{} {}".format("Li hua", 24)
兩者效果一樣。
拓展:該字段完整語法格式為arg_name(.attribute_name | [element_index])*
,是在arg_name對應的值為對象、列表或字典時使用,獲取其進一步的屬性值或者內部值。
這里舉一個例子:
>>> "{0[name]} {0[age]}, {1[0]} {1[1]}".format({"name": "Li hua", "age": 24}, ["Zhang san",24])
'Li hua 24, Zhang san 24'
conversion
選填。變換,不常用。
指定時要用!
來開頭,指定后會在格式化之前將arguments
中對應的值進行類型變換。
其有三個值可以指定,分別為
conversion |
說明 |
---|---|
s |
調用結果對象的str 方法進行轉換 |
r |
調用結果對象的repr 方法進行轉換 |
a |
調用結果對象的ascii 方法進行轉換 |
format_spec
選填,格式化具體規范,核心內容,超常用。
填寫時要用:
來開頭,填寫后,會按照其指定的規則來進行格式化。
其詳細語法為
[[fill]align][sign][#][0][width][grouping_option][.precision][type]
其中所有字段均為選填,下面依次介紹下(其中加粗的為常用),
fill
: 填充內容,如果指定了寬度,但變量長度不夠,會使用該字段值進行填充。設置了fill,后面必須顯式設置align。align
: 對齊方式,有以下值:
align |
說明 |
---|---|
< |
強制左對齊(絕大多數對象默認使用) |
> |
強制右對齊(數字類型默認使用) |
= |
強制將填充內容放在符號(如果有)之后但數字之前,比如輸出成+000000120 這樣的格式。此對齊選項僅對數字類型有效。(當'0'緊接在字段寬度width 之前時,它將成為默認值。) |
^ |
強制居中對齊 |
sign
: 符號展現格式,僅對數字類型有效。有以下值:
sign |
說明 |
---|---|
+ |
正數負數都展現符號,正數用+,負數用-。 |
- |
(默認值),僅負數展現符號。 |
|
負數展現符號,正數前面使用一個空格來占位對齊。 |
-
#
: 復雜生僻,基本不使用,不介紹,有需要的可查閱官方文檔(見本部分開頭)。 -
0
: 當沒有設置對齊方式align
時, 在寬度字段前面加一個零('0')字符,將等價於填充字符fill
為0
且對齊方式align
為<
。 -
width
: 最小字段寬度,不設置則字段寬度將始終與填充它的數據長度相同(此時對齊方式align
沒有意義)。 -
grouping_option
: 分組選擇,有兩個選項可選:
grouping_option |
說明 |
---|---|
, |
表示使用逗號作為千位分隔符。 |
_ |
復雜生僻,基本不使用,不介紹. |
-
precision
: 精度,指定時要用.
來開頭,是一個十進制數,指定用'f'和'f'格式化的浮點值在小數點后應該顯示多少位,即保留幾位小數。 -
type
: 類型,決定數據應該如何顯示。
有很多值,這里只介紹幾個常用的:
type |
說明 |
---|---|
s |
字符串格式。這是字符串的默認類型,可以省略(不填) |
d |
十進制整數 |
f |
十進制浮點數(小數), 默認保留六位小數 |
補充說明1: fill, align只有設置了width才能生效。
簡單示例
>>> "{:4}{:6},{:10}".format("1", "2", 3.14) # set width
'1 2 , 3.14'
>>> "{:4}{:>6}, {:^10}".format("1", "2", 3.14) # set width, align
'1 2, 3.14 '
>>> "{:_<4}{:0>6}, {:^10}".format("1", "2", 3.14) # set width, align, fill
'1___000002, 3.14 '
>>> "{:_<4}{:0>6}, {:^10.4f}".format("1", "2", 3.14) # set width, align, fill, precision, type
'1___000002, 3.1400 '
3 - f 表達式
參考文檔:
https://docs.python.org/3/reference/lexical_analysis.html#formatted-string-literals
http://zetcode.com/python/fstring/
這是從Python 3.6開始的一個新功能。
f表達式(f-string), 又名(formatted string literal), 是前綴為“f”或“f”, 用花括號{}
包裹替換字段的字符串文字。
其簡易格式為: f'{name} is {age} years old'
。
其中花括號{}
包裹的是替換字段replacement_field
,相當於上面的占位符,
但是不同於占位符是先占住位置最后標明變量進行替換,f表達式里的替換字段直接在花括號里面進行變量替換。
上面的例子就是用name
變量值替換{name}
字段,用age
變量值替換{age}
字段。
f表達式詳細格式為:
f'(literal_char | {{ | }} | replacement_field)*'
F'(literal_char | {{ | }} | replacement_field)*'
以上說明f表達式中的字符串內容,是由任意個literal_char
、{{
、}}
、replacement_field
自由組成的。
其中literal_char是除花括號{}
外的任意字符或空。
f表達式中要表示花括號{}
文本,需要進行轉義,轉義方式為{{
, }}
,
replacement_field
是替換字段,是f表達式的核心。
其格式為
{f_expression[=][!conversion][:format_spec]}
- 替換字段由花括號包裹
f_expression
: 必填內容,常規Python表達式,一般要被圓括號包圍,只有少數注意事項:
不允許使用空表達式。
lambda和賦值表達式:=
必須用顯式括號括起來。
替換表達式可以包含換行符(例如在三重引號字符串中),但不能包含注釋。
每個表達式在格式化字符串文本出現的上下文中按從左到右的順序進行計算。
其完整格式為:
(conditional_expression | * or_expr) (, conditional_expression | , * or_expr)* [,] | yield_expression
過於復雜,只展示不介紹,詳情可查閱官方文檔:https://docs.python.org/3/reference/lexical_analysis.html#grammar-token-f-expression
=
: 選填(3.8新版功能), 在表達式后添加等號'=', 可以顯示表達式文本及其求值后的值(在調試中很有用),。conversion
: 選填。轉換,指定時要在開頭添加!
,指定后對表達式求值的結果在格式化之前進行轉換。
下方示例中,name = "Ståle"
conversion |
說明 | 示例 | 輸出 |
---|---|---|---|
s |
對結果調用str() 方法 |
f"His name is {name!s}." |
'His name is Ståle.' |
r |
對結果調用repr() 方法 |
f"His name is {name!r}." |
"His name is 'Ståle'." |
a |
對結果調用ascii() 方法 |
f"His name is {name!a}." |
"His name is 'St\xe5le'." |
format_spec
: 格式規范, 和本文第二部分format
中的format_spec
格式規范是一樣的。
不過這里的可以嵌套使用replacement_field
指定其中的值。
>>> line = "The output will have the expression text"
>>> f"{line = }" # use "=" sign, require python 3.8 or above
'line = "The output will have the expression text"'
>>> width = 10
>>> precision = 4
>>> value = 12.34567
>>> f"result: {value:{10}.{4}}" # set format_spec
'result: 12.35'
>>> f"result: {value:{width}.{precision}}" # nested fields
'result: 12.35'