有多种字符串格式设置方法:

Python<2.6:“您好%s”%namePython 2.6+:“Hello{}”.format(name)(使用str.format)Python 3.6+:f“{name}”(使用f-string)

哪种情况更好?在什么情况下?


以下方法具有相同的结果,那么有什么区别?name=“爱丽丝”“你好%s”%name“您好{0}”.format(名称)f“您好{name}”#使用命名参数:“您好%(kwarg)s”%{'kwarg':name}“你好{kwarg}”.format(kwarg=name)f“您好{name}”字符串格式化何时运行,如何避免运行时性能损失?


如果您试图结束一个重复的问题,该问题只是在寻找一种格式化字符串的方法,请使用How do I put a variable value in a string?。


当前回答

对于python版本>=3.6(参见PEP 498)

s1='albha'
s2='beta'

f'{s1}{s2:>10}'

#output
'albha      beta'

其他回答

假设您使用的是Python的日志模块,您可以将字符串格式化参数作为参数传递给.debug()方法,而不是自己进行格式化:

log.debug("some debug info: %s", some_info)

这避免了进行格式化,除非记录器实际记录了一些内容。

从Python 3.6(2016)开始,您可以使用f-string替换变量:

>>> origin = "London"
>>> destination = "Paris"
>>> f"from {origin} to {destination}"
'from London to Paris'

注意f“前缀。如果您在Python3.5或更早版本中尝试此操作,将得到SyntaxError。

看见https://docs.python.org/3.6/reference/lexical_analysis.html#f-字符串

%比我测试的格式性能更好。

测试代码:

Python 2.7.2:

import timeit
print 'format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')")
print '%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')")

结果:

> format: 0.470329046249
> %: 0.357107877731

Python 3.5.2

import timeit
print('format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')"))
print('%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')"))

后果

> format: 0.5864730989560485
> %: 0.013593495357781649

在Python2中,差异很小,而在Python3中,%比格式快得多。

感谢@Chris Cogdon提供的示例代码。

编辑1:

2019年7月在Python 3.7.2中再次测试。

结果:

> format: 0.86600608
> %: 0.630180146

没有太大区别。我想Python正在逐步改进。

编辑2:

在有人在评论中提到python 3的f-string之后,我在python 3.7.2下测试了以下代码:

import timeit
print('format:', timeit.timeit("'{}{}{}'.format(1, 1.23, 'hello')"))
print('%:', timeit.timeit("'%s%s%s' % (1, 1.23, 'hello')"))
print('f-string:', timeit.timeit("f'{1}{1.23}{\"hello\"}'"))

结果:

format: 0.8331376779999999
%: 0.6314778750000001
f-string: 0.766649943

似乎f-string仍然比%慢,但比格式好。

但是请注意,刚才我在尝试用现有代码中的.format替换所有%时发现了一个问题:“{}”.format(unicode_string)将尝试对unicode_string进行编码,并且可能会失败。

看看这个Python交互式会话日志:

Python 2.7.2 (default, Aug 27 2012, 19:52:55) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
; s='й'
; u=u'й'
; s
'\xd0\xb9'
; u
u'\u0439'

s只是一个字符串(在Python3中称为“byte array”),u是一个Unicode字符串(在Python 3中称“string”):

; '%s' % s
'\xd0\xb9'
; '%s' % u
u'\u0439'

当您将Unicode对象作为参数提供给%operator时,即使原始字符串不是Unicode,它也会生成Unicode字符串:

; '{}'.format(s)
'\xd0\xb9'
; '{}'.format(u)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u0439' in position 0: ordinal not in range(256)

但.format函数将引发“UnicodeEncodeError”:

; u'{}'.format(s)
u'\xd0\xb9'
; u'{}'.format(u)
u'\u0439'

并且只有当原始字符串是Unicode时,它才能使用Unicode参数。

; '{}'.format(u'i')
'i'

或者如果参数字符串可以转换为字符串(称为“字节数组”)

回答第一个问题。格式在许多方面似乎更为复杂。关于%的一个令人讨厌的问题是,它可以接受变量或元组。你会认为以下方法总是有效的:

"Hello %s" % name

然而,如果name恰好是(1,2,3),它将抛出一个TypeError。为了保证它总是打印出来,你需要

"Hello %s" % (name,)   # supply the single argument as a single-item tuple

这太难看了。格式没有这些问题。同样在您给出的第二个示例中,.format示例看起来更简洁。

仅用于向后兼容Python 2.5。


为了回答第二个问题,字符串格式化与任何其他操作同时发生-当计算字符串格式化表达式时。Python不是一种惰性语言,它在调用函数之前会对表达式求值,因此表达式log.debug(“somedebuginfo:%s”%some_info)将首先将字符串求值为,例如“somedebug-info:roflcopters is active”,然后将该字符串传递给log.debug()。