f-string格式化字符串
自Python 3.6开始加入标准库。您可以在PEP 498中阅读所有内容。f-string,一种改进Python格式字符串的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快!
f-string在形式上是以 f 或 F 修饰符引领的字符串(f’xxx’ 或 F’xxx’),以大括号 {} 标明被替换的字段;f-string在本质上并不是字符串常量,而是一个在运行时运算求值的表达式。
f-string在功能方面不逊于传统的%-formatting语句和str.format()函数,同时性能又优于二者,且使用起来也更加简洁明了,因此对于Python3.6及以后的版本,推荐使用f-string进行字符串格式化。
例如:
1
2
3
4
|
name = "Tom"
age = 44
s = f"Hello, {name}. You are {age}."
print(s) # 输出Hello, Tom. You are 44.
|
使用大写字母F也是有效的:
1
2
3
4
|
name = "Eric"
age = 74
s = F"Hello, {name}. You are {age}."
print(s) # 输出Hello, Eric. You are 74.
|
由于f-string是在运行时进行渲染的,因此可以将任何有效的Python表达式放入其中。这可以让你做一些漂亮的事情。
你可以做一些非常简单的事情,就像这样:
f”{2 * 37}” #输出 74
你可以调用函数
1
2
3
|
name = "Eric"
s = f"{name.lower()} is funny."
print(s) # 输出eric is funny.
|
f-string语法
1
2
3
|
("{{" | "}}" | "{" f_expression ["!" conversion] [":" format_spec] "}")*
conversion ::= "s" | "r" | "a"
format_spec ::= (literal_char | NULL | replacement_field)*
|
花括号外部的字符串部分按字面处理,除了任何两个的花括号’{{‘或’}}‘替换为相应的单个花括号。单个开口花括号’{‘标记替换字段,以Python表达式开头。在表达式之后,可能存在由感叹号’!‘引入的转换字段。还可以附加格式说明符,由冒号’:’引入。替换字段以右侧括号’}‘结尾。
格式化字符串文字中的表达式被视为由括号括起来的常规Python表达式,但有一些例外。不允许使用空表达式,并且lambda表达式必须由显式括号括起来。表达式可以包含换行符(例如,在三引号字符串中),但它们不能包含注释。
如果指定了转换,则在格式化之前转换计算表达式的结果。转换’!s’在结果上调用str(),’!r’调用repr(),’!a’调用ascii()。然后使用format()协议格式化结果。
format_spec语法(同str.format()方法一样)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
{[[fill]align][sign][#][0][width][,][.precision][type]}
fill 可选,可以是任何字符
align 可选,是对齐方式,可供选择的值有:
'<' 左对齐
'>' 右对齐
'=' 只对数字类型有效
'^'居中对齐
sign 可选,是对齐方式,可供选择的值有:
'+' 表示正负数字都应使用符号。正数前加正号,负数前加负号;
'-' 表示符号只能用于负数(这是默认行为)。正数前无符号,负数前加负号;
' ' 正数前加空格,负数前加负号;
# 可选,用于转换。 对于不同类型,替代形式的定义不同。 此选项仅对integer,float,complex和Decimal类型有效。 对于整数,当使用二进制,八进制或十六进制输出时,此选项将前缀“0b”,“0o”或“0x”添加到输出值。 对于浮点数,复数和十进制,备用形式会导致转换结果始终包含小数点字符,即使后面没有数字也是如此。 通常,只有在跟随数字的情况下,这些转换的结果中才会出现小数点字符。 此外,对于“g”和“G”转换,不会从结果中删除尾随零。
width 可选,数字宽度,表示总共输出多少位数字
.precision 可选,小数点后保留的位数,进行四舍五入计算。
typecode 可选
s : 获取传入对象的__str__方法的返回值,并将其格式化到指定位置
r : 获取传入对象的__repr__方法的返回值,并将其格式化到指定位置
c : 如果是整数的话,将数字转换成其unicode对应的值,10进制范围为0 <= i <= 1114111(py27则只支持0-255);如果是字符的话,将字符添加到指定位置
o : 将整数转换成八进制表示,并将其格式化到指定位置
x : 将整数转换成十六进制表示,并将其格式化到指定位置
d : 将整数、浮点数转换成十进制表示,并将其格式化到指定位置
e : 将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)
E : 将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)
f : 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)
F : 同上
g : 自动调整将整数、浮点数转换成浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)
G : 自动调整将整数、浮点数转换成浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)
% : 百分比。将数字乘以100,并以固定格式(“f”)显示,后跟百分号。
|
格式化字符串文字的一些示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
>>> name = "Fred"
>>> f"He said his name is {name!r}."
"He said his name is 'Fred'."
>>> f"He said his name is {repr(name)}." # repr()等同于!r
"He said his name is 'Fred'."
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}" # 嵌套字段
'result: 12.35'
>>> today = datetime(year=2017, month=1, day=27)
>>> f"{today:%B %d, %Y}" # 利用date的format specifier
'January 27, 2017'
>>> number = 1024
>>> f"{number:#0x}" # 利用整数的format specifier
'0x400'
|
你甚至可以使用带有f-string的类创建对象。想象一下你有以下类:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Comedian:
def __init__(self, first_name, last_name, age):
self.first_name = first_name
self.last_name = last_name
self.age = age
def __str__(self):
return f"{self.first_name} {self.last_name} is {self.age}."
def __repr__(self):
return f"{self.first_name} {self.last_name} is {self.age}. Surprise!"
new_comedian = Comedian("Eric", "Idle", "74")
s = f"{new_comedian}"
print(s) #输出Eric Idle is 74.
|
__str ()和repr ()方法处理对象如何呈现为字符串,因此您需要确保在类定义中包含至少一个这些方法。如果必须选择一个,请使用repr (),因为它可以代替str __()。
__str ()返回的字符串是对象的非正式字符串表示,应该可读。repr ()返回的字符串是官方表示,应该是明确的。调用str()和repr()比直接使用str ()和repr __()更好。
默认情况下,f字符串将使用__str (),但如果包含转换标志!r,则可以确保它们使用repr __():
例如:
1
2
3
4
|
f"{new_comedian}"
#输出 Eric Idle is 74.
f"{new_comedian!r}"
#输出 Eric Idle is 74. Surprise!
|
多行f-string
例如:
1
2
3
4
|
message = (f"Hi {name}. "
f"You are a {profession}. "
f"You were in {affiliation}.")
print(message) #输出Hi Eric. You are a comedian. You were in Monty Python.
|
但请记住,您没必要将f放在多行字符串的每一行的前面。以下代码也能work:
1
2
3
4
|
message = (f"Hi {name}. "
"You are a {profession}. "
"You were in {affiliation}.")
print(message) #输出Hi Eric. You are a {profession}. You were in {affiliation}.
|
注意事项
引号
您可以在表达式中使用各种类型的引号。只要确保在表达式中使用的f-string外部没有使用相同类型的引号即可。
以下写法都是正确的:
1
2
3
4
5
6
|
f"{'Eric Idle'}" #输出Eric Idle
f"'Eric Idle'" #输出'Eric Idle'
f'{"Eric Idle"}' #输出Eric Idle
f'"Eric Idle"' #输出"Eric Idle"
f"""Eric Idle""" #输出Eric Idle
f'''Eric Idle''' #输出Eric Idle
|
字典
说到引号,注意你在使用字典的时候。如果要为字典的键使用单引号,请记住确保对包含键的f-string使用双引号。
以下代码是有效的:
1
2
|
comedian = {'name': 'Eric Idle', 'age': 74}
f"The comedian is {comedian['name']}, aged {comedian['age']}." #输出The comedian is Eric Idle, aged 74.
|
但是,以下代码就是一个语法错误:
1
2
3
4
|
f'The comedian is {comedian['name']}, aged {comedian['age']}.'
File "<ipython-input-40-cd7d8a3db23b>", line 1
f'The comedian is {comedian['name']}, aged {comedian['age']}.'
SyntaxError: invalid syntax
|
如果您在字典键周围使用与在f-string外部使用相同类型的引号,则第一个字典键开头的引号将被解释为字符串的结尾。
大括号
为了使字符串出现大括号,您必须使用双大括号:
例如:
1
2
3
4
5
6
7
|
name = "Tom"
s1 = F"Hello, {name}. "
s2 = F"Hello, {{name}}. "
s3 = F"Hello, {{{name}}}. "
print(s1) #输出Hello, Tom. #替换变量name的值
print(s2) #输出Hello, {name}. #两个{{替换为{,{失去应有的替换作用,name作为字符串打印出来。
print(s3) #输出Hello, {Tom}. #前两个{{替换为{,第三个{将变量name替换为Tom,所以结果是{Tom}。
|
反斜杠
正如您之前所看到的,您可以在f-string的字符串部分使用反斜杠转义符。但是,您不能使用反斜杠在f-string的表达式部分中进行转义:
例如:
1
2
3
4
5
6
|
print(f"\"I am {'Eric Idle'}\"") #输出"I am Eric Idle"
print(f"\"I am {\'Eric Idle\'}\"") #报错
File "main.py", line 1
print(f"\"I am {\'Eric Idle\'}\"")
^
SyntaxError: f-string expression part cannot include a backslash
|
lambda表达式
如果您需要使用lambda表达式,请记住,lambda表达式必须由显式括号括起来。
例如:
1
2
3
4
|
f"{lambda x: x * 37(2)}"
File "<fstring>", line 1
(lambda x)
SyntaxError: unexpected EOF while parsing
|
您可以通过将您的lambda嵌套在圆括号中来解决此问题:
1
2
|
f"{(lambda x: x * 37)(2)}"
74
|
转载请注明本网址。