Python的字符串格式化的许多方式-较旧的(即将被淘汰)吗?


106

Python至少有六种格式化字符串的方式:

In [1]: world = "Earth"

# method 1a
In [2]: "Hello, %s" % world
Out[2]: 'Hello, Earth'

# method 1b
In [3]: "Hello, %(planet)s" % {"planet": world}
Out[3]: 'Hello, Earth'

# method 2a
In [4]: "Hello, {0}".format(world)
Out[4]: 'Hello, Earth'

# method 2b
In [5]: "Hello, {planet}".format(planet=world)
Out[5]: 'Hello, Earth'

# method 2c
In [6]: f"Hello, {world}"
Out[6]: 'Hello, Earth'

In [7]: from string import Template

# method 3
In [8]: Template("Hello, $planet").substitute(planet=world)
Out[8]: 'Hello, Earth'

不同方法的简要历史:

  • printf自从Python诞生以来,样式样式格式化就已经存在
  • Template班是在Python 2.4中引入
  • format方法在Python 2.6中引入
  • f-strings是在Python 3.6中引入的

我的问题是:

  • 是否printf不赞成使用-style格式?
  • 在中Template class,该substitute方法是否已弃用或将要弃用?(我不是在谈论safe_substitute,据我所知它提供了独特的功能)

类似的问题以及为什么我认为它们不是重复的:

也可以看看


1
我需要指出您忘记了Formatter课程吗?
马丁·彼得斯

Answers:


14

尽管在文档中有各种各样的迹象表明,.formatf字符串优于%字符串,但尚无可行的方案来弃用后者。

在提交的问题#14123中:明确提及旧样式%字符串格式有一些警告,但不会很快消失。,受问题启发,表明目前没有计划弃用printf样式格式,有关%-formatting 的文档已被编辑为包含以下短语:

由于新的字符串格式语法更加灵活并且可以自然地处理元组和字典,因此建议将其用于新代码。但是,目前没有废弃过printf样式格式的计划

(强调我的。)

此短语稍后在commit Close#4966中删除:修改序列文档,以更好地解释现代Python的状态。这看起来似乎是一个迹象,表明不再支持%格式化的计划已经重新出现在卡上了……但是,深入研究Bug跟踪程序后,发现其意图恰恰相反。在错误跟踪器上,提交的作者描述了更改的特征,如下所示

  • 更改了描述printf样式格式与str.format方法之间关系的散文(故意消除了前者可能会消失的真正危险的暗示-认真考虑将其销毁是不切实际的)

换句话说,我们对%-formatting文档进行了两次连续更改,旨在明确强调不会被弃用,更不用说删除了。这些文档仍然对不同类型的字符串格式的相对优点持保留意见,但他们也清楚%格式不会被弃用或删除。

更重要的是,该段落的最新更改是在2017年3月,对此进行了更改...

此处描述的格式化操作表现出各种古怪,这些古怪会导致许多常见错误(例如无法正确显示元组和字典)。使用较新的格式化字符串文字或str.format接口有助于避免这些错误。这些替代方法还提供了更强大,灵活和可扩展的文本格式设置方法。

...对此:

此处描述的格式化操作表现出各种古怪,这些古怪会导致许多常见错误(例如无法正确显示元组和字典)。使用更新的格式化字符串文字,str.format接口或模板字符串可能有助于避免这些错误。这些选择中的每一个都提供了自己的权衡,并带来了简单性,灵活性和/或可扩展性的好处。

请注意,从“避免使用帮助”到“可以避免使用”的变化,以及关于.formatf和弦的清晰建议如何被蓬松,模棱两可的散文所取代,有关每种样式如何“提供自己的取舍和好处”。也就是说,不仅不再正式弃用卡片,而且当前的文档公开承认%格式至少比其他方法具有一些“好处”。

从这一切中我可以推断出,弃用或删除%格式的运动不仅步履蹒跚,而且被彻底永久地击败。


2
添加了蓬松的语言更改,以使Mercurial维护人员(以及其他人)安于不想使Mercurial留下的代码库太大而无法消除的使用%。现在,“无大规模代码修改”政策已被取消,他们的反对也在逐渐消失。从长远来看,保持这两种形式% 在某种程度上都没有好处,无论如何都会删除printf语法。我们只是不知道什么时候,所以该语言值得淡化。
的Martijn Pieters的

@MartijnPieters有趣。听起来您对我缺乏的这一决定有很多了解。对于它的价值,我认为从您那里得到一个引人入胜的答案,概述这些要点(作为新答案,或者对您现有的答案进行修改)将有价值。
Mark Amery

58

.format()方法旨在替换旧的%格式语法。后者已经不再强调,(但没有正式弃用尚未)。方法文档指出:

字符串格式化的这种方法是在Python 3的新标准,并应首选%格式化中所描述的字符串的格式化操作在新的代码。

(强调我的)。

为了保持向后兼容性,并让您更容易过渡,旧格式已经被留在原地现在。根据最初的PEP 3101提案

向后兼容

可以通过保留现有机制来保持向后兼容性。新系统不会与现有字符串格式化技术的任何方法名称发生冲突,因此这两个系统可以共存,直到需要弃用旧系统为止。

请注意,直到该淘汰旧系统为止;它尚未被弃用,但是只要您编写新代码,就将使用新系统

新系统的一个优点是您可以结合使用旧%格式化程序的元组和字典方法:

"{greeting}, {0}".format(world, greeting='Hello')

并可以通过 object.__format__()用于处理各个值格式钩子进行。

请注意,旧系统具有%Template类,后者允许您创建添加或更改其行为的子类。新型系统具有Formatter一流填充相同细分市场。

Python 3进一步远离了弃用,而是在printf-style String Formatting部分中给您警告:

注意:此处描述的格式化操作表现出各种古怪,导致许多常见错误(例如未能正确显示元组和字典)。使用较新的格式化字符串文字str.format()接口有助于避免这些错误。这些替代方法还提供了更强大,灵活和可扩展的文本格式设置方法。

Python 3.6还添加了格式化的字符串文字,将表达式内联格式字符串中。这些是使用内插值创建字符串的最快方法,应使用它,而不是str.format()在可以使用文字的任何地方。


4
并且,Formatter您可以创建自定义格式,例如datetime对象使用的格式。另外,由于.format是函数,您可以使用它来更直接地创建可调用的惰性格式:fmt = '{} - {}'.format; fmt(a, b)
Jon Clements

我怎么没看到Template有关%或对旧系统。尤其是您链接的PEP指出,尽管该提案与和之间存在一些重叠string.Template,但可以认为每个提案都满足不同的需求,而一个提案不能消除另一个提案。在您的答案中,您可能会感到困惑,即Template作为旧系统一部分的格式也已被弃用。
Bakuriu

@Bakuriu:对,我想我错过了那部分;但我认为这Formatter门课可以满足相同的需求string.Template()
Martijn Pieters

1
[...]should be preferred to the % formatting[...]此部分已从文档中删除。docs.python.org/3/library/stdtypes.html#str.format
AXO

我认为这个答案目前令人误解;引用的第一篇文章已从Python 3文档中删除,对我来说似乎很清楚,没有多余的意图进行弃用。这个答案仍然具有历史价值,但是我倾向于调整措辞以避免任何暗示仍然存在贬值的建议,并将答案的前半部分编辑为过去时。如果您不反对,我会在某个时候这样做,但我想我会先发表评论,如果您愿意的话,您可以自己进行此类更改。
Mark Amery

45

%尽管有其他答案,但不建议使用字符串格式的运算符,并且不会删除该运算符。
每次在Python开发列表中提出该主题时,都会有一个关于哪个更好的争论,但是对于是否要删除经典方法却没有争议-它会一直存在。尽管在PEP 3101上有说明,但Python 3.1来了又去了,%格式化仍然存在。

保持经典风格的说法很明确:它很简单,很快,可以快速完成简短的事情。使用该.format方法并不总是那么容易理解-几乎没有人-即使在核心开发人员中,也可以使用所提供的完整语法,.format而无需查看参考资料甚至在2009年,就有这样的消息:http:// mail。 python.org/pipermail/python-dev/2009-October/092529.html 几乎没有出现该主题。

2016年更新

在当前的Python开发版本(将成为Python 3.6)中,有第三种字符串内插方法,如PEP-0498所述。它定义了一个新的报价前缀f""(除了当前的u""b""r"")。

给字符串加上前缀f将在运行时在字符串对象上调用一个方法,该方法将自动将当前作用域中的变量插入到字符串中:

>>> value = 80
>>> f'The value is {value}.'
'The value is 80.'

3
允许类型实现自己的更好__format__。例如,format(Decimal('0.1'), '.20f')vs '%.20f' % Decimal('0.1')。后者将十进制强制为浮点数。
Eryk Sun

2
注意 我并不是说旧样式在所有方面都更好-只是它更短,有时更易读(有时不是)。当然,新方法更加灵活。
jsbueno 2015年

fPython 3中有与之等效的功能吗?
丹尼尔(Daniel)

f-strings如上所使用的语言中的新功能,像Python 3.6的。它在以前的版本中不存在,并且会在这些版本上引发语法错误。
jsbueno

20

圭多对此的最新立场似乎在这里指出:

Python 3.0的新增功能

PEP 3101:字符串格式化的新方法

用于内置字符串格式化操作的新系统取代了%字符串格式化运算符。(但是,仍然支持%运算符;它将在Python 3.1中弃用,并在以后的某个时间从语言中删除。)有关完整说明,请阅读PEP 3101。

PEP3101本身,它有最后的修改可以追溯到(周五,2011年9月30日),这样的晚的,一个没有进步,我想。


18

在查看较旧的Python文档和PEP 3101时,有一条语句表示将来将不推荐使用%运算符并将其从该语言中删除。在下面的语句是在Python文档的Python 3.0,3.1和3.2:

由于str.format()很新,因此许多Python代码仍然使用%运算符。但是,由于最终会从该语言中删除这种旧的格式设置样式,因此通常应使用str.format()。

如果转到Python 3.3和3.4文档中的同一部分,您将看到该语句已被删除。我也无法在文档中的任何其他地方找到任何其他声明,表明该运算符将不推荐使用或从该语言中删除。还需要注意的是,PEP3101两年半没有进行过修改(2011年9月30日,星期五)。

更新资料

PEP461接受将%格式添加到字节和字节数组中,并且应该是Python 3.5或3.6的一部分。这是%运算符还活着而且在踢的另一个迹象。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.