微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

python – string.Formatter抛出KeyError”

我想打印出像 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之后:仅适用于非字符串类型(例如和 – )

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐