Python 2.6引入了str.format()方法,其语法与现有的 %
运算符略有不同 . 哪种情况更好,哪种情况更好?
- 以下使用每种方法并具有相同的结果,那么有什么区别?
#!/usr/bin/python
sub1 = "python string!"
sub2 = "an arg"
a = "i am a %s" % sub1
b = "i am a {0}".format(sub1)
c = "with %(kwarg)s!" % {'kwarg':sub2}
d = "with {kwarg}!".format(kwarg=sub2)
print a # "i am a python string!"
print b # "i am a python string!"
print c # "with an arg!"
print d # "with an arg!"
- 此外,何时在Python中发生字符串格式化?例如,如果我的日志记录级别设置为HIGH,我仍然会执行以下
%
操作?如果是这样,有没有办法避免这种情况?
log.debug("some debug info: %s" % some_info)
15 回答
正如我今天发现的那样,通过
%
格式化字符串的旧方法不支持Decimal
,Python的十进制定点和浮点运算模块,开箱即用 .示例(使用Python 3.3.5):
输出:
肯定可能有解决办法,但你仍然可以考虑立即使用
format()
方法 .回答你的第一个问题...
.format
在许多方面看起来更复杂 . 关于%
的一个烦人的事情也是它如何能够采用变量或元组 . 您认为以下内容始终有效:但是,如果
name
碰巧是(1, 2, 3)
,它将抛出TypeError
. 为了保证它始终打印,您需要这样做这只是丑陋的 .
.format
没有这些问题 . 同样在你给出的第二个例子中,.format
示例看起来更清晰 .你为什么不用它?
不知道它(我在阅读之前)
必须与Python 2.5兼容
要回答第二个问题,字符串格式化与任何其他操作同时发生 - 评估字符串格式化表达式时 . 并且Python不是一种惰性语言,在调用函数之前会对表达式求值,因此在
log.debug
示例中,表达式"some debug info: %s"%some_info
将首先求值,例如"some debug info: roflcopters are active"
,然后该字符串将传递给log.debug()
.如果你的python> = 3.6,F字符串格式的文字是你的新朋友 .
它更简单,更干净,性能更好 .
%
比我的测试中的format
性能更好 .测试代码:
Python 2.7.2:
结果:
Python 3.5.2
结果
它看起来在Python2中,差异很小,而在Python3中,
%
比format
快得多 .感谢@Chris Cogdon提供的示例代码 .
但有一件事是,如果你有嵌套的大括号,将不适用于格式,但
%
将起作用 .例:
假设你是're using Python' s
logging
模块,你可以将字符串格式化参数作为参数传递给.debug()
方法,而不是自己进行格式化:这避免了格式化,除非 Logger 实际记录的东西 .
作为旁注,您不必为了使用新的样式格式与日志记录而受到性能影响 . 您可以将任何对象传递给实现
__str__
魔术方法的logging.debug
,logging.info
等 . 当日志记录模块确定它必须发出消息对象(无论它是什么)时,它会在执行此操作之前调用str(message_object)
. 所以你可以这样做:这些都在Python 3文档(https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles)中描述 . 但是,它也适用于Python 2.6(https://docs.python.org/2.6/library/logging.html#using-arbitrary-objects-as-messages) .
使用这种技术的一个优点,除了它的格式化风格不可知的事实,是它允许惰性值,例如上面的函数
expensive_func
. 这为Python文档中提供的建议提供了更优雅的替代方案:https://docs.python.org/2.6/library/logging.html#optimization ..format
的另一个优点(我在答案中没有看到):它可以采用对象属性 .或者,作为关键字参数:
据我所知,
%
无法做到这一点 .对于python版本> = 3.6(参见PEP 498)
从Python 3.6(2016)开始,您可以使用f-strings替换变量:
注意
f"
前缀 . 如果您在Python 3.5或更早版本中尝试此操作,您将获得SyntaxError
.见https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings
模数运算符(%)不能做的事情,afaik:
结果
很有用 .
另一点:作为函数的
format()
可以在其他函数中用作参数:结果是:
%
可能有用的一种情况是在格式化正则表达式时 . 例如,提出
IndexError
. 在这种情况下,您可以使用:这可以避免将正则表达式写为
'{type_names} [a-z]{{2}}'
. 当你有两个正则表达式时,这可能很有用,其中一个正则单独使用而没有格式,但两者的串联都是格式化的 .但是请小心,刚才我在现有代码中尝试用
.format
替换所有%
时发现了一个问题: '{}'.format(unicode_string) will try to encode unicode_string and will probably fail.看看这个Python交互式会话日志:
s
只是一个字符串(在Python3中称为'byte array'),u
是一个Unicode字符串(在Python3中称为'string'):当您将一个Unicode对象作为参数提供给
%
运算符时,即使原始字符串不是Unicode,它也会生成一个Unicode字符串:但是
.format
函数会引发"UnicodeEncodeError":只有当原始字符串是Unicode时,它才能使用Unicode参数 .
或者如果参数字符串可以转换为字符串(所谓的'字节数组')
PEP 3101建议用Python 3中新的高级字符串格式替换
%
运算符,它将是默认值 .我想补充一点,自3.6版以来,我们可以使用如下的fstrings
哪个给
Everything is converted to strings
结果:
you can pass function, like in others formats method
举个例子