在Python 2.7.6中,这两者都有效:
>>> '{0} {1}'.format('hello', 'world')
'hello world'
>>> '{} {}'.format('hello', 'world')
'hello world'
但其中只有一项有效:
>>> from string import Formatter
>>> Formatter().format('{0} {1}', 'hello', 'world')
'hello world'
>>> Formatter().format('{} {}', 'hello', 'world')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/string.py", line 545, in format
return self.vformat(format_string, args, kwargs)
File "/usr/lib/python2.7/string.py", line 549, in vformat
result = self._vformat(format_string, args, kwargs, used_args, 2)
File "/usr/lib/python2.7/string.py", line 571, in _vformat
obj, arg_used = self.get_field(field_name, args, kwargs)
File "/usr/lib/python2.7/string.py", line 632, in get_field
obj = self.get_value(first, args, kwargs)
File "/usr/lib/python2.7/string.py", line 591, in get_value
return kwargs[key]
KeyError: ''
为什么str.format
和string.Formatter.format
以这种方式有所不同,虽然我在文档中找不到任何暗示这一点的内容?这种差异是否意图和/或记录在哪里?
答案 0 :(得分:2)
此问题/错误已raised here。它已在Python3.5中修复。
它尚未针对Python2.7进行修补。在此之前,您可以继承string.Formatter
来实现自动arg索引:
import string
class AutoArgFormatter(string.Formatter):
"""
Backport of https://hg.python.org/cpython/rev/ad74229a6fba to Python2.7
"""
def _vformat(self, format_string, args, kwargs, used_args, recursion_depth,
auto_arg_index=0):
if recursion_depth < 0:
raise ValueError('Max string recursion exceeded')
result = []
for literal_text, field_name, format_spec, conversion in \
self.parse(format_string):
# output the literal text
if literal_text:
result.append(literal_text)
# this is some markup, find the object and do
# the formatting
# handle arg indexing when empty field_names are given.
if field_name == '':
if auto_arg_index is False:
raise ValueError('cannot switch from manual field '
'specification to automatic field '
'numbering')
field_name = str(auto_arg_index)
auto_arg_index += 1
elif field_name.isdigit():
if auto_arg_index:
raise ValueError('cannot switch from manual field '
'specification to automatic field '
'numbering')
# disable auto arg incrementing, if it gets
# used later on, then an exception will be raised
auto_arg_index = False
# given the field_name, find the object it references
# and the argument it came from
obj, arg_used = self.get_field(field_name, args, kwargs)
used_args.add(arg_used)
# do any conversion on the resulting object
obj = self.convert_field(obj, conversion)
# expand the format spec, if needed
format_spec = self._vformat(format_spec, args, kwargs,
used_args, recursion_depth-1,
auto_arg_index=auto_arg_index)
# format the object and append to the result
result.append(self.format_field(obj, format_spec))
return ''.join(result)
fmt = AutoArgFormatter()
print(fmt.format('{} {}', 'hello', 'world'))
产量
hello world