python字符串格式suppress / silent keyerror / indexerror [重复]

问题描述 投票:16回答:4

有没有办法使用python string.format,这样当索引丢失时不会抛出异常,而是插入一个空字符串。

result = "i am an {error} example string {error2}".format(hello=2,error2="success")

在这里,结果应该是:

"i am an   example string success"

现在,python抛出了一个keyerror并停止格式化。是否有可能改变这种行为?

谢谢

编辑:

存在Template.safe_substitute(即使使模式保持原样而不是插入空字符串),但对于string.format可能没有类似的东西

期望的行为类似于php中的字符串替换。

class Formatter(string.Formatter):
  def get_value(self,key,args,kwargs):
    try:
        if hasattr(key,"__mod__"):
            return args[key]
        else:
            return kwargs[key]
    except:
        return ""

这似乎提供了期望的行为。

string format python
4个回答
18
投票

str.format()不期望一个映射对象。试试这个:

from collections import defaultdict

d = defaultdict(str)
d['error2'] = "success"
s = "i am an {0[error]} example string {0[error2]}"
print s.format(d)

你使用返回“”的str()工厂制作一个defaultdict。然后为defaultdict创建一个键。在格式字符串中,您可以访问传递的第一个对象的键。这样做的好处是允许你传递其他键和值,只要你的defaultdict是format()的第一个参数。

另外,请参阅http://bugs.python.org/issue6081


12
投票

格式映射中字符串的官方解决方案(Python 3 Docs)是对dict类进行子类化并定义魔术方法__missing__()。只要缺少某个键,就会调用此方法,而它返回的内容则用于字符串格式:

class format_dict(dict):
    def __missing__(self, key):
        return "..."

d = format_dict({"foo": "name"})

print("My %(foo)s is %(bar)s" % d) # "My name is ..."

print("My {foo} is {bar}".format(**d)) # "My name is ..."

编辑:第二个print()在Python 3.5.3中有效,但它不在例如3.7.2:KeyError: 'bar'被提升,我找不到抓住它的方法。

经过一些实验,我发现Python的行为有所不同。在v3.5.3中,调用是成功的__getitem__(self, "foo")和无法找到密钥__getitem__(self, "bar")"bar",因此它调用__missing__(self, "bar")来处理丢失的密钥而不抛出KeyError。在v3.7.2中,__getattribute__(self, "keys")在内部被调用。内置的keys()方法用于返回键上的迭代器,产生“foo”,__getitem__("foo")成功,然后迭代器耗尽。对于来自格式字符串的{bar},没有关键的"bar"__getitem__()__missing_()没有被要求处理这种情况。而是抛出KeyError。我不知道怎么会抓住它,如果有的话。

在Python 3.2+中你应该使用format_map()(也见Python Bug Tracker - Issue 6081):

from collections import defaultdict

d = defaultdict(lambda: "...")
d.update({"foo": "name"})

print("My {foo} is {bar}".format_map(d)) // "My name is ..."

如果要保留占位符,可以执行以下操作:

class Default(dict):
    def __missing__(self, key): 
        return key.join("{}")

d = Default({"foo": "name"})

print("My {foo} is {bar}".format_map(d)) // "My name is {bar}"

如你所见,format_map()确实打电话给__missing__()

以下似乎是最兼容的解决方案,因为它也适用于较旧的Python版本,包括2.x(我测试了v2.7.15):

class Default(dict):
    def __missing__(self, key):
        return key.join("{}")

d = Default({"foo": "name"})

import string
print(string.Formatter().vformat("My {foo} is {bar}", (), d)) // "My name is {bar}"

5
投票

不幸的是,不,默认情况下没有这样的方法。但是,您可以使用重写的__getattr__提供defaultdict或object,并使用如下所示:

class SafeFormat(object):
    def __init__(self, **kw):
        self.__dict = kw

    def __getattr__(self, name):
        if not name.startswith('__'):
            return self.__dict.get(name, '')

print "i am an {0.error} example string {0.error2}".format(SafeFormat(hello=2,error2="success"))
i am an  example string success

3
投票

我创建的版本与Daniel的方法类似,但没有{0.x}属性访问权限。

import string    
class SafeFormat(object):
    def __init__(self, **kw):
        self.__dict = kw

    def __getitem__(self, name):
        return self.__dict.get(name, '{%s}' % name)



string.Formatter().vformat('{what} {man}', [], SafeFormat(man=2))

打印出来

'{what} 2'
© www.soinside.com 2019 - 2024. All rights reserved.