Python 2.6引入了str.format()
方法,其语法与现有的%
运算符略有不一样。 哪一个更好,什么状况下适合? html
如下使用每种方法并具备相同的结果,那么有什么区别? python
#!/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中进行字符串格式化? 例如,若是个人日志记录级别设置为“高”,执行如下%
操做是否还会受到影响? 若是是这样,有办法避免这种状况吗? linux
log.debug("some debug info: %s" % some_info)
可是请当心,当我尝试在现有代码.format
全部%
替换为.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中称为“字节数组”),而u
是Unicode字符串(在Python3中称为“字符串”): 函数
; '%s' % s '\xd0\xb9' ; '%s' % u u'\u0439'
当您将Unicode对象做为参数提供给%
运算符时,即便原始字符串不是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参数一块儿使用。 spa
; '{}'.format(u'i') 'i'
或者参数字符串能够转换为字符串(所谓的“字节数组”) debug
正如我今天发现的那样,经过%
格式化字符串的旧方法不支持Decimal
(即用于十进制定点和浮点算术的Python模块)。
示例(使用Python 3.3.5):
#!/usr/bin/env python3 from decimal import * getcontext().prec = 50 d = Decimal('3.12375239e-24') # no magic number, I rather produced it by banging my head on my keyboard print('%.50f' % d) print('{0:.50f}'.format(d))
输出:
0.00000000000000000000000312312239239009009464850 0.00000000000000000000000312375239000000000000000000
固然可能有解决方法,可是您仍然能够考虑当即使用format()
方法。
附带说明,您没必要为了提升性能而在日志记录中使用新样式格式。 您能够将实现__str__
magic方法的任何对象传递给logging.debug
, logging.info
等。 当日志记录模块决定必须发出您的消息对象(不管它是什么)时,它会先调用str(message_object)
。 所以,您能够执行如下操做:
import logging class NewStyleLogMessage(object): def __init__(self, message, *args, **kwargs): self.message = message self.args = args self.kwargs = kwargs def __str__(self): args = (i() if callable(i) else i for i in self.args) kwargs = dict((k, v() if callable(v) else v) for k, v in self.kwargs.items()) return self.message.format(*args, **kwargs) N = NewStyleLogMessage # Neither one of these messages are formatted (or calculated) until they're # needed # Emits "Lazily formatted log entry: 123 foo" in log logging.debug(N('Lazily formatted log entry: {0} {keyword}', 123, keyword='foo')) def expensive_func(): # Do something that takes a long time... return 'foo' # Emits "Expensive log entry: foo" in log logging.debug(N('Expensive log entry: {keyword}', keyword=expensive_func))
全部这些都在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
另外一个优势(我在答案中没有看到):它能够采用对象属性。
In [12]: class A(object): ....: def __init__(self, x, y): ....: self.x = x ....: self.y = y ....: In [13]: a = A(2,3) In [14]: 'x is {0.x}, y is {0.y}'.format(a) Out[14]: 'x is 2, y is 3'
或者,做为关键字参数:
In [15]: 'x is {a.x}, y is {a.y}'.format(a=a) Out[15]: 'x is 2, y is 3'
据我所知, %
是不可能的。
在格式化正则表达式时, %
可能会有所帮助的一种状况。 例如,
'{type_names} [a-z]{2}'.format(type_names='triangle|square')
引起IndexError
。 在这种状况下,您可使用:
'%(type_names)s [a-z]{2}' % {'type_names': 'triangle|square'}
这样能够避免将正则表达式写为'{type_names} [az]{{2}}'
。 当您有两个正则表达式时,这颇有用,其中一个正则表达式单独使用而没有格式,可是两个正则表达式的链接都已格式化。