最原始的方式应该就是用 % 操作符了,% 操作符可以按位置替换格式化符的值:
name = "earth"
return "hello %s" % name
hello earth
若有超过一个的值要格式化则需要把这些值组成一个元组:
name = "earth"
age = 4600000000
return "%s is %d old" % (name,age)
earth is 4600000000 old
不过 % 也可以按名字进行替换,这个时候 % 后面应该接一个dict:
info = {"name": "earth", "age": 4600000000, "alias": "Gaia"}
return "%(name)s is %(age) old" % info
earth is 42213467000ld
注意到,使用字典格式化时并不要求字典里的元素个数与格式化符的个数一致。Python 支持的格式化符可以在这里看到 https://docs.python.org/3/library/stdtypes.html
字符串的 format 方法也支持按位置和按名字两种方式进行格式化:
按位置进行格式化:
name = "earth"
age = 4600000000
return "{} is {:f} old".format(name,age)
earth is 4600000000.000000 old
其中 {} 表示变量替换的位置。
按名字进行格式化:
name = "earth"
age = 4600000000
return "{name} is {age:f} old".format(age=age,name=name)
earth is 4600000000.000000 old
注意,它的格式化符是在 {} 中加上 :x 的后缀,关于 format 方法的格式化符可以参见 https://docs.python.org/3/library/string.html
不仅如此,format的 {} 内还能有更复杂的东西:
return "{info[0]} is {info[1]} old".format(info=("earth",4600000000))
earth is 4600000000 old
然而,这可能带来安全方面的隐患:
SECRET = 'this-is-a-secret'
class Error:
def __init__(self):
pass
err = Error()
user_input = '{error.__init__.__globals__[SECRET]}'
print(user_input.format(error=err))
this-is-a-secret
Python 的标准库中提供了一个 Template 类,可以进行简单的内容替换。
from string import Template
name = "earth"
age = 4600000000
templ = Template("$name is $age old")
return templ.substitute(name=name,age=float(age))
earth is 4600000000.0 old
注意,模板字符串并别有格式化符这种东西,因此要让 age 以浮点型形式显示需要用 float 函数先转成浮点型,使用模板字符串的优点在于比较安全,比如上面那个 format 方法的隐患,改成用模板字符,则会报错。
from string import Template
SECRET = 'this-is-a-secret'
class Error:
def __init__(self):
pass
err = Error()
user_input = '${error.__init__.__globals__[SECRET]}'
try:
Template(user_input).substitute(error=err)
except ValueError as e:
print(e)
Invalid placeholder in string: line 1, col 1
Template 的这个特性特别适用于格式化字符串是由外人提供的情况时使用。
这种格式化字符串的方法是由 Python 3.6 新加入的,它允许你在字符串内内嵌 Python 运算式:
a = 11
b = 2
return f'{a} + {b} = {a + b};{a} - {b} = {a - b}'
11 + 2 = 13;11 - 2 = 9
它也同时支持 str.format() 方法中的那些格式化符,且使用方法也一样:
num = 222
return f'{num} 的16进制表示是 {num:#x}'
222 的16进制表示是 0xde
有这么多种方法格式化字符串,该如何抉择呢?一个建议:


