一共四种风格,printf(百分号),format 方法,模板,fstring。
我看有地方把加号也算进来,加号可以说是字符串连接方式,算格式化么?
甚至有地方把 print
传参算进来,无语。
printf-style 字符串格式化
也就是百分号风格。
标记 | 含义 |
---|---|
# |
- |
0 |
zero padding |
- |
左对齐 |
|
- |
+ |
正负号 |
符号 | 含义 |
---|---|
d , i , u |
int |
o |
int(八进制,octal) |
x |
int(十六进制,hexadecimal) |
X |
int(十六进制,hexadecimal,大写) |
e |
float(指数格式) |
E |
float(指数格式,大写) |
f , F |
float |
g |
e or f |
G |
E or f |
c |
字符(int, string) |
r |
字符串(repr) |
s |
字符串(str) |
a |
字符串(ascii) |
% |
百分号 |
https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting
https://docs.python.org/3/library/stdtypes.html#printf-style-bytes-formatting
"%s" % "hello"
"%s" % ((1, 2), ) # "%s" % a, 如果 a 是元组,就踩坑了
"%(a)s + %(b)s" % {"a": 1, "b": 2}
Format String (format 方法)
https://docs.python.org/3/library/string.html#formatspec
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][z][#][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" | "%"
conversion 中的 rsa 分别表示 repr,str,ascii。
符号 | 含义 |
---|---|
b |
二进制 |
c |
字符 |
d ,n |
十进制 |
o |
八进制 |
x |
十六进制 |
X |
十六进制,大写 |
这套语法要强大很多。
"hi, {}!".format("jim") # hi, jim!
"{2} {2}, {1} {1}, {0} {0}".format('a', 'b', 'c') # c c, b b, a a
"{a:d} {a:08b}".format(a=7) # 7 00000111
"{:+10.2f}".format(1 / 3)
# ' +0.33'
"{:-10.2f}".format(1 / 3)
# ' 0.33'
'{:.2%}'.format(1 / 3)
# '33.33%'
'{:>10.2%}'.format(1 / 3)
'{:<10.2%}'.format(1 / 3)
'{:=10.2%}'.format(1 / 3)
'{:^10.2%}'.format(1 / 3) # 居中对齐
'{:x}'.format(11) # b
'{:#x}'.format(11) # 0xb
'{:#X}'.format(11) # 0XB
Template String 模板
https://docs.python.org/3/library/string.html#template-strings
from string import Template
s = Template('$who likes $what')
s.substitute(who='tim', what='kung pao')
# 'tim likes kung pao'
d = dict(who='tim')
Template('Give $who $100').substitute(d)
# Traceback (most recent call last):
# ...
# ValueError: Invalid placeholder in string: line 1, col 11
Template('$who likes $what').substitute(d)
# Traceback (most recent call last):
# ...
# KeyError: 'what'
Template('$who likes $what').safe_substitute(d)
'tim likes $what'
Formatted string literals (f-string / fstring)
Python 3.6 引入。大体上是继承 Format String 语法,但是更加完备,更加方便。
参考:PEP 498, Eric V. Smith, 2015/08
https://docs.python.org/3/reference/lexical_analysis.html#f-strings
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>
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() is equivalent to !r
"He said his name is 'Fred'."
width = 10
precision = 4
value = decimal.Decimal("12.34567")
f"result: {value:{width}.{precision}}" # nested fields
'result: 12.35'
today = datetime(year=2017, month=1, day=27)
f"{today:%B %d, %Y}" # using date format specifier
'January 27, 2017'
f"{today=:%B %d, %Y}" # using date format specifier and debugging
'today=January 27, 2017'
number = 1024
f"{number:#0x}" # using integer format specifier
'0x400'
foo = "bar"
f"{ foo = }" # preserves whitespace
" foo = 'bar'"
line = "The mill's closed"
f"{line = }"
'line = "The mill\'s closed"'
f"{line = :20}"
"line = The mill's closed "
f"{line = !r:20}"
'line = "The mill\'s closed" '