我想打印出像
this question这样的键值对,
key a: 1 key ab: 2 key abc: 3 ^ this colon is what I want
但我不喜欢那里的答案,我试图像这样继承string.Formatter:
from __future__ import print_function from string import Formatter class KeyFormatter(Formatter): def parse(self,fmtstr): res = super(KeyFormatter,self).parse(fmtstr) #for r in res: # print(r) return res kf = KeyFormatter() w = 10 x = dict(a=1,ab=2,abc=3) for k in sorted(x): v = x[k] print(kf.format('key {::<{}} {}',k,w,v))
我想调试解析,看看我是否可以在格式字符串中插入额外的’:’,但这会抛出一个
KeyError:”
在Python 2.7和3.4中.如果我取消注释for循环以查看错误中的内容消失,但最终的print语句只显示换行符.
当我做最后一行时:
print('key {:<{}} {}'.format(k,v))
这工作(键后有空格),当我这样做时:
print('key {::<{}} {}'.format(k,v))
我得到多个’:’而不是空格.但没有KeyError.
为什么我会得到KeyError?我该怎么调试呢?
解决方法
这里有两个有些相关的问题,如何调试的简单答案是:你不能,至少不能使用print语句,或者使用字符串格式化的任何东西,因为这种情况发生在另一种字符串格式中并破坏了格式化程序的状态.
它抛出一个错误是由于string.Formatter()不支持空字段的事实,这是格式从2.6到3.1(和2.7)的补充,这是在C代码中,但没有反映在字符串模块中.
您可以通过继承类MyFormatter来模拟新行为:
from __future__ import print_function from string import Formatter import sys w = 10 x = dict(a=1,abc=3) if sys.version_info < (3,): int_type = (int,long) else: int_type = (int) class MyFormatter(Formatter): def vformat(self,*args): self._automatic = None return super(MyFormatter,self).vformat(*args) def get_value(self,key,args,kwargs): if key == '': if self._automatic is None: self._automatic = 0 elif self._automatic == -1: raise ValueError("cannot switch from manual field specification " "to automatic field numbering") key = self._automatic self._automatic += 1 elif isinstance(key,int_type): if self._automatic is None: self._automatic = -1 elif self._automatic != -1: raise ValueError("cannot switch from automatic field numbering " "to manual field specification") return super(MyFormatter,self).get_value(key,kwargs)
应该摆脱KeyError.之后你应该覆盖方法format_field而不是parse:
if sys.version_info < (3,): string_type = basestring else: string_type = str class TrailingFormatter(MyFormatter): def format_field(self,value,spec): if isinstance(value,string_type) and len(spec) > 1 and spec[0] == 't': value += spec[1] # append the extra character spec = spec[2:] return super(TrailingFormatter,self).format_field(value,spec) kf = TrailingFormatter() w = 10 for k in sorted(x): v = x[k] print(kf.format('key {:t:<{}} {}',v))
得到:
key a: 1 key ab: 2 key abc: 3
请注意格式说明符(t),它在格式字符串中引入尾随字符.
Python格式化例程实际上足够聪明,可以让您在字符串中插入尾随字符,就像宽度格式一样:
print(kf.format('key {:t{}<{}} {}',':',v))
给出相同的结果,让你动态改变’:’
您还可以将format_field更改为:
def format_field(self,spec): if len(spec) > 1 and spec[0] == 't': value = str(value) + spec[1] # append the extra character spec = spec[2:] return super(TrailingFormatter,spec)
并交给任何类型:
print(kf.format('key {:t{}<{}} {}',(1,2),'@',10,3))
要得到:
key (1,2)@ 3
但是,因为在将值转换为字符串之前将值转换为Formatter.formatfield(),如果str(val)获得的值与使用{0} .format(val)和/或选项不同,则可能会得到不同的结果在t之后:仅适用于非字符串类型(例如和 – )