加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – string.Formatter抛出KeyError”

发布时间:2020-12-20 13:07:12 所属栏目:Python 来源:网络整理
导读:我想打印出像 this question这样的键值对, key a: 1key ab: 2key abc: 3 ^ this colon is what I want 但我不喜欢那里的答案,我试图像这样继承string.Formatter: from __future__ import print_functionfrom string import Formatterclass KeyFormatter(For
我想打印出像 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之后:仅适用于非字符串类型(例如和 – )

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读