f-strings
从 Python 3.6 开始, 新引入了一种字符串格式化方法, 称为 "格式化字符串常量"(formatted string literal), 简称 f-strings. 相比于 %,str.format,string.Template 这些字符串格式化方法, f-strings 在功能上一点不逊色, 性能更优, 而且更易读, 更简洁, 也不易出错. 如果你使用的是 Python3.6 以上的版本, 建议你使用 f-strings 来格式化字符串.
f-strings 是以 f 或 F 打头的字符串, 形如 f'Ilove {name}',F'I am {name} and I am {age} years old.'. 请注意, 在 f(或 F)与引号之间不要有空格, 否则会引起语法错误. 另外, 对于 f 后面字符串的引号, 你可以使用单引号, 双引号或三引号, 但是要配对使用, 不可出现交叉, 相同引号不能嵌套, 这与创建普通字符串时对引号的使用要求是一样的. f-strings 提供了一种把表达式嵌入字符串中的方法, 而且语法相当简洁, 我们只需要把表达式直接放入一对花括号中就行了. 请注意, f-strings 中可以有多个花括号, 但这些花括号必须成对出现, 不允许有单个左花括号或右花括号存在. 程序运行时会计算表达式的值, 并使用结果值替换表达式, 最终形成一个完整的字符串. 这里所说的 "表达式" 可以是任意表达式, 包括变量, 函数, 各种运算表达式, 条件表达式, 以及 lambda 表达式等.
- >>> name = 'Lily'
- # 使用单引号
- >>> f'I love {name}'
- 'I love Lily'
- # f 和'之间有空格
- >>> f 'I love {
- name
- }'
- SyntaxError: invalid syntax
- # 使用双引号
- >>> f"I love {name}"
- 'I love Lily'
- # 使用三引号
- >>> f'''I love {name}'''
- 'I love Lily'
- >>> f'''I love {name},
- and Jack loves {name},too.''''I love Lily,\nand Jack loves Lily,too.'
- # 调用字符串的 upper()函数
- # 把名字转换为大写
- >>> f'I love {name.upper()}'
- 'I love LILY'
- >>> f'The area of the circle is{3.14*2*2}'
- 'The area of the circle is 12.56'
当 f-strings 引用字典中的值时, 一定要特别注意引号使用的问题, 相同引号不要进行嵌套.
- # 单引号出现了嵌套
- >>> dic = {
- 'name':'Lily','age':18
- }
- >>> f'I am {dic['name']},and I am{dic['age']} years old.'
- SyntaxError: invalid syntax
- >>> f'I am{dic["name"]},and I am {dic["age"]} years old.'
- 'I am Lily,and I am 18 years old.'
如果字符串本身就包含花括号, 要求原样保留在最终结果中, 为此需要在 f-strings 中使用两个花括号进行转义. 连续两个左花括号代表结果字符串中一个左花括号, 连续两个右括号代表结果字符串中的一个右括号.
- >>> f'{{{"lily".upper()} }}'
- '{ LILY }'
- >>>f'{{{"lily".upper()}}}'
- '{LILY}'
- # 连续两个花括号之间不能有空格
- >>> f'{ {{"lily".upper()} }}'
- Traceback (most recent call last):
- File "<pyshell#68>", line 1, in <module>
- f'{ { {"lily".upper()} }}'
- TypeError: unhashable type: 'set'
除了表达式之外, 花括号中还可以有格式说明符, 如下:
- >>> f'π的值是{pi:.2f}'
- 'π的值是 3.14'
- >>> f'{75:+#010x}'
- '+0x000004b'
f-strings 的完整形式如下:
注: 上面中的 [] 表示是可选的.
- 表达式(expression): 对于表达式, 我们应该注意如下几点:
f-strings 要求花括号中必须有表达式.
f-strings 可以包含任意表达式, 它可以是变量, 常量, 各种运算表达式, 条件表达式, 函数等. 当然, f-strings 中的表达式可以是 lambda 表达式, 但 lambda 表达式中的冒号 (:) 容易被 f-strings 误认为是表达式和格式说明符之间的冒号分隔符. 为了避免出现这个问题, 使用 lambda 表达式时, 需要先把它放入到一个圆括号里面, 然后再放入花括号中, 例如:
- >>> import math
- >>> r = 3
- >>> f'半径为 {r} 的圆的面积是:{(lambda r:math.pi*r*r)(r):.2f}'
- '半径为 3 的圆的面积是: 28.27'
表达式中不应该包含: 或! 两个符号, 但这两个符号允许出现在表达式所包含的字符串之中.
表达式中也不允许出现反斜杠(\), 也就是说, 我们无法在表达式中使用转义字符进行转义操作(但转义字符可以用在 text 之中进行转义).
以 #打头的文本不允许直接出现在表达式中. 但允许出现在表达式所包含的字符串之中.
表达式中允许出现!= 运算符
- 类型转换标志: 类型转换标志和 str.format()的类型转换标志一样, 有三个可能的取值, 分别是! s,!r,!a. 设置为! s 表示调用 str()对表达式进行转换 (默认方式);!r 表示调用 repr() 对表达式进行转换;!a 表示调用 ascii()对表达式进行转换. 这些转换发生在调用 format()函数使用格式说明符对表达式做格式化之前.
- 格式说明符 (format specifier):f-strings 的格式说明符和 str.format() 的格式说明符是一样的. 给出了格式化说明符之后, 这些说明符会被作为参数传入__format__函数对表达式的值进行格式化, 若不指定格式说明符, 则向__format__函数传入空字符串. 有关格式说明符的内容, 我们在前面讲解 str.format()时已经讲过了, 这里就不再赘述了.
请注意: 格式化说明符中可以嵌套使用表达式. f-strings 执行时会先计算这些嵌套表达式, 得到完整的格式化说明符, 然后再使用格式化说明符格式化外层表达式. 例如:
- >>> pi= 3.1415926
- >>>width = 10
- >>>precision = 3
- >>> f'π的值是:{pi:{width}.{precision}f}'
- 'π的值是: 3.142'
下面举一些使用格式化说明符的例子:
- >>>import math
- >>>math.pi
- 3.141592653589793
- # * 指填充符号
- # ^ 居中对齐
- # + 显示符号
- # 10 是替换字段宽度
- # .3 是精度
- # f 是浮点数
- >>>f'The value of PI is {math.pi:*^+10.3f}'
- 'The value of PIis **+3.142**'
- # =: 内容右对齐, 且只对数字类型有效.
- # 若有符号, 将其放在填充字符左侧,
- # 形成 "符号 + 填充字符 + 数字" 的格式
- >>>f'The value of PI is {math.pi:*=+10.3f}'
- 'The value of PIis +****3.142'
- # #表示显示二进制, 八进制, 十六进制前缀
- # 0 表示空白处填充 0, 相当于把 fill 设置为 0 且使用 = 对齐方式.
- # 10 替换字段宽度
- # X 表示把十进制整数转换成十六进制数
- >>>f'{55:+#010X}'
- '+0X0000037'
- # , 为千分位符号
- >>>digit = 45724561
- >>>f'The digit is {digit:+015,d}'
- 'The digit is+00,045,724,561'
友情提示: 有关格式化说明符的详细内容, 请参考公众号里介绍 str.format()的文章, 那里有非常详细的讲解.
"人生苦短, 要学 Python"
在 f-strings 中, f 和 r(或 R)可以结合使用, 且先后顺序任意(fr 或 rf), 用以创建原生 f-strings. 上面讲解中, 我们提到在 f-strings 的花括号外面的字符串中可以使用转义字符进行转义处理. 但, 若 f-strings 前面使用了 fr 或 rf 作为前缀, 则这些转义字符会被当成普通的字符, 失去转义功能, 这在构建正则表达式时会非常有用.
- >>> print(f'I love\n{"Lily"}')
- I love
- Lily
- # 原生 f-strings
- # 转义字符被当成普通字符
- # 失去转义功能
- >>> print(fr'I love\n{"Lily"}')
- I love\n Lily
另外, 相邻的 f-strings 和普通字符串会自动连接在一起. 两个相邻的普通字符串会在编译时连接起来, 而 f-strings 只有运行时才进行连接.
- >>> name1 = 'Lily'
- >>> name2 = 'Python'
- >>> 'I''love'f'{name1}'f'{"and":^5}'f'{name2}''I love Lily and Python'
- # 各个字符串之间可以有任意多个空格
- # 连接时这些空格会被忽略
- >>> 'I' 'love' f'{name1}' f'{"and":^5}' f'{name2}'
- 'I love Lily and Python'
尽管 f-strings 支持把整个表达式写入 {} 之中, 但有时这样做会引起困扰, 比如:
- >>> f'{{1:2,3:4}}'
- '{1:2,3:4}'
- >>> f'{ {1:2,3:4} }'
- '{1: 2, 3: 4}'
在第一个 f-strings 例子中, 外层 {} 与内层 {} 之间没有空格, 所以里面的 {{和}} 是用来做转义, 分别表示一个左花括号 ({) 和一个右花括号(}), 这从结果字符串中可以看到这一点.
而在第二个 f-strings 例子中, 外层 {} 与内层 {} 之间有空格, 内层 {} 表示的是一个字典, 外层 {} 表示对内层字典表达式求值, 结果是字典本身. 我们可以把第二个 f-strings 例子改写为:
- >>> dic = {
- 1:2,3:4
- }
- >>> f'{dic}'
- '{1: 2, 3: 4}'
有些表达式直接写在 f-strings 中, 容易产生令人困惑的结果. 对于这样的表达式, 建议大家不要把整个表达式放入 f-strings 之中, 而像上面改写的那样分开写, 这可以让 f-strings 变得更加清晰可读.
值得注意的是, f-strings 也可以用来格式化日期时间. 不同于普通字符串, 日期时间有自己的一套格式化方法. 使用 f-strings 格式化日期时间时, 前面提到的格式化说明符将不再起作用, 必须使用日期时间特有的格式化符号, 具体有哪些格式化符号, 请参照下表.
格式化符号 | 含义 | 举例 |
%a | 星期几(本地缩写) | Sun, Mon, …, Sat |
%A | 星期几(本地全名) | Sunday, Monday, …, Saturday |
%w | 星期几(以十进制数 0-6 表示,0 代表星期天,6 代表星期六) | 0, 1, …, 6 |
%u | 星期几(ISO 8601 标准,以十进制数表示,1 代表星期一) | 1, 2, …, 7 |
%d | 日(以两位十进制数表示,不足两位用 0 补齐) | 01, 02, …, 31 |
%b | 月份(本地缩写) | Jan, Feb, …, Dec |
%B | 月份(本地全名) | January, February, …, December |
%m | 月份(以两位十进制数表示,不足两位用 0 补齐) | 01, 02, …, 12 |
%y | 年(年份后两位数,以两位十进制数表示,不足两位用 0 补齐) | 00, 01, …, 99 |
%Y | 年(以四位十进制数表示,不足四位用 0 补齐) | 0001, 0002, …, 2013, 2014, …, 9998, 9999 |
%G | 年(ISO8601 标准,以四位十进制数表示,不足四位用 0 补齐,包含 ISO 大部分周(%V)) | 0001, 0002, …, 2013, 2014, …, 9998, 9999 |
%H | 时(24 时制,以两位十进制数表示,不足两位用 0 补齐) | 00, 01, …, 23 |
%I | 时(12 时制,以两位十进制数表示,不足两位用 0 补齐) | 01, 02, …, 12 |
%p | 上午 / 下午的本地表示 | AM, PM |
%M | 分(以两位十进制数表示,不足两位用 0 补齐) | 00, 01, …, 59 |
%S | 秒(以两位十进制数表示,不足两位用 0 补齐) | 00, 01, …, 59 |
%f | 微秒(以六位十进制数表示,不足六位用 0 补齐) | 000000, 000001, …, 999999 |
%z | UTC 偏移(格式为 ±HHMM[SS[.ffffff]],若未指定时区,则返回空字符串) | +0000, -0400, +1030, +063415, -030712.345216 |
%Z | 时区名(若未指定时区,则返回空字符串) | UTC, EST, CST |
%j | 一年中的第几天(以三位十进制数表示,不足三位用 0 补齐) | 001, 002, …, 366 |
%U | 一年中的第几周(以星期天作为星期的第一天,以两位十进制数表示,不足两位用 0 补齐,全年第一个星期天之前的那个周称为第 0 周) | 00, 01, …, 53 |
%W | 一年中的第几周(以星期一作为星期的第一天,以两位十进制数表示,不足两位用 0 补齐,全年第一个星期一之前的那个周称为第 0 周) | 00, 01, …, 53 |
%V | 一年中的第几周(ISO8601 标准,以星期一作为星期的第一天,以两位十进制数表示,不足两位用 0 补齐,包含 1 月 4 日的那一周为第 01 周) | 00, 01, …, 53 |
%c | 适合本地的日期时间表示 | Tue Aug 16 21:30:00 1988 (en_US); Di 16 Aug 21:30:00 1988 (de_DE) |
%x | 适合本地的日期表示 | 08/16/88 (None); 08/16/1988 (en_US); 16.08.1988 (de_DE) |
%X | 适合本地的时间表示 | 21:30:00 (en_US); 21:30:00 (de_DE) |
%% | 百分号 | % |
%T | 显示时分秒(格式 hh:mm:ss) | 10:47:00 |
%D | 显示月日年(格式 mm/dd/yy) | 01/12/19 |
%R | 显示时分(格式 hh:mm) | 10:47 |
%t | 水平制表符 | |
%n | 换行 | |
%F | 显示年月日(格式 yyyy-mm-dd) | 2019-01-12 |
- >>> import datetime
- >>> dt = datetime.datetime.today()
- >>> f'The time is {dt:%Y-%m-%d %a%H:%M:%S}'
- 'The time is 2019-01-12 Sat 10:47:00'
- >>> f'The time is {dt:%F %a %T}'
- 'The time is 2019-01-12 Sat 10:47:00'
关注我
"人生苦短, 要学 Python"
来源: https://www.cnblogs.com/jeonhae/p/10270228.html