TOC

Python f-string

以前的字符串格式换方法

1. format 方法格式化

这种方法用的不多(对应 string.Formatter)。

Format String Syntax

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"

field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
arg_name          ::=  [identifier | digit+]
attribute_name    ::=  identifier
element_index     ::=  digit+ | index_string
index_string      ::=  <any source character except "]"> +

conversion        ::=  "r" | "s" | "a"

format_spec       ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]
fill              ::=  <any character>
align             ::=  "<" | ">" | "=" | "^"
sign              ::=  "+" | "-" | " "
width             ::=  digit+
grouping_option   ::=  "_" | ","
precision         ::=  digit+
type              ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
print('{} {}'.format('Hello', 'World'))
print('There are three people in my family: {0}, {1}, and I, and I love my {0} a litte more.'.format('father', 'mother'))

2. 模板字符串格式化

这种方法我只在文档中看到,从没真的用过。
PS: 被废弃的 PEP 215 曾建议采用 $'a = $a, b = $b' 这种语法。

Template strings

from string import Template
Template('$who likes $what').substitute(who='tim', what='kung pao')
Template('$who likes $what').safe_substitute({'who': 'time'})

3. 百分号格式化

这应该是现在的最主流的字符串格式化方式。

printf-style String Formatting

print('Hello %s' % 'World')
print('action %s cost %.3f seconds' % ('download', 0.123456789))
print('%(language)s has %(number)03d quote types.' % {'language': "Python", "number": 2})

Python 3.6 新加入 f-string

Formatted string literals

f_string          ::=  (literal_char | "{{" | "}}" | replacement_field)*
replacement_field ::=  "{" f_expression ["="] ["!" conversion] [":" format_spec] "}"
f_expression      ::=  (conditional_expression | "*" or_expr)
                         ("," conditional_expression | "," "*" or_expr)* [","]
                       | yield_expression
conversion        ::=  "s" | "r" | "a"
format_spec       ::=  (literal_char | NULL | replacement_field)*
literal_char      ::=  <any code point except "{", "}" or NULL>

format 方法格式化语法中复用了很多 (格式化和 conversion 部分), 不过变得更强大了。
主要是里面支持条件语句,表达式 (包括 yield)。

a = 3.1415926
f'{a}'
f'{a:.2f}'

f"{1 + 1}", f"{{1 + 1}}", f"{{{1 + 1}}}"
# ('2', '{1 + 1}', '{2}')

注意:f-sting 里面不能使用反斜杠转义!

f'{John\'s}'
# SyntaxError: f-string expression part cannot include a backslash

r, s, a

  • !r -> repr()
  • !s -> str()
  • !a -> ascii()

PS: ascii 方法是 Python 3 引入,和 repr 相似,但是 ascii 方法仅使用 ASCII 字符。
例如:a = '中国'; print(f'{a!a} {ascii(a)}') 输出 '\u4e2d\u56fd' '\u4e2d\u56fd'

print(f'{a!r}')

=

有人提议加入 !d 表示输出表达式本身,然后加上等于号,加上计算值,例如 f'1 + 1!d' => 1 + 1=2
后来实现成了这样:

a = 3.14
b = 1
print(f'a + b=')   # a + b=4.140000000000001
print(f'a + b = ') # a + b = 4.140000000000001

很有趣!

参考资料与拓展阅读