模板旨在比通常的字符串格式化更简单,代价是表达能力较弱。 PEP 292的原理比较了模板和Python的%
风格的字符串格式化:
目前Python支持基于C的
printf()
'%'格式化字符的字符串替换语法。虽然非常丰富, 但是即使是有经验的Python程序员也容易出错。一个常见的错误是遗漏尾部格式字符,例如在%(name)s
中遗漏s
。此外,%后面可以跟随什么规则相当复杂,而通常应用程序很少需要这种复杂性。 大多数脚本需要进行一些字符串插值,但是其中大部分使用简单的格式化格式,即
%s
或%(name)s
。 这种形式应该变得更简单且不易出错。
尽管新的.format()
改善了情况,但仍然存在格式字符串语法相当复杂的问题。因此,PEP 292的原理仍然有其优点。
字符串模板的一个关键优势是,您可以使用safe_substitute
方法仅替换某些占位符。如果未传递值给占位符,则普通格式化字符串将引发错误。例如:
"Hello, {first} {last}".format(first='Joe')
引起:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'last'
但是:
from string import Template
Template("Hello, $first $last").safe_substitute(first='Joe')
输出:
'Hello, Joe $last'
请注意,返回的值是一个字符串,而不是Template
对象;如果您想要替换$last
,则需要从该字符串创建一个新的Template
对象。
{variant_text}_\d{4}
类型的语法,因为通常的 str.format()
函数需要为 '4' 提供一个值。这解决了这个问题。如果可以的话,我会给它 10 个赞。 - S3DEV就性价比而言,使用字典进行模板替换似乎比格式化替换慢4到10倍,具体取决于模板的长度。以下是我在装有Python 3.5的2.3 GHz Core i7上在OS X下运行的快速比较。
from string import Template
lorem = "Lorem ipsum dolor sit amet {GIBBERISH}, consectetur adipiscing elit {DRIVEL}. Expectoque quid ad id, quod quaerebam, respondeas."
loremtpl = Template("Lorem ipsum dolor sit amet $GIBBERISH, consectetur adipiscing elit $DRIVEL. Expectoque quid ad id, quod quaerebam, respondeas.")
d = dict(GIBBERISH='FOOBAR', DRIVEL = 'RAXOOP')
In [29]: timeit lorem.format(**d)
1.07 µs ± 2.13 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [30]: timeit loremtpl.substitute(d)
8.74 µs ± 12.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
我测试的最坏情况是对于一个13个字符的字符串,速度慢了大约10倍。我测试的最好情况是对于一个71000个字符的字符串,速度慢了大约4倍。
这主要是一种语法偏好的问题,通常涉及到懒惰/冗长的权衡以及对现有字符串模板系统的熟悉程度和习惯。在这种情况下,模板字符串更加懒惰/简单/快速编写,而.format()
则更冗长且功能丰富。
熟悉PHP语言或Jinja系列模板系统的程序员可能更喜欢使用模板字符串。使用“%s”定位样式元组替换可能会吸引那些使用类似于printf
的字符串格式化或需要快速完成任务的人。.format()
具有更多功能,但除非您需要仅由.format()
提供的特定功能,否则使用任何现有方案都没有问题。
唯一需要注意的是,命名字符串模板比顺序相关的模板更灵活,需要更少的维护。除此之外,所有的一切都归结为个人偏好或您所在项目的编码标准;
string.Template('bob is $age years old').substitute(age=age)
与'bob is {age} years old'.format(age)
。 - danio以下是来自本文的一个示例:
CONFIG = {"SECRET_KEY": "super secret key"}
class Event:
def __init__(self, id_, level, message):
self.id_ = id_
self.level = level
self.message = message
def format_event(format_string, event):
return format_string.format(event=event)
# user supplied template
inp = "{event.__init__.__globals__[CONFIG][SECRET_KEY]}"
event = Event(1234, "foo", "boo")
print(format_event(inp, event))
输出:
super secret key
{}
更有可能自然地出现在一段文本中,而不是$foo
或${foo}
(例如在生成源代码时)。这意味着使用模板时,您需要花费更少的精力来转义这些适当文本的出现。