在使用kwargs时,如何在Python format()中转义冒号?
我想打印一本带冒号的字典。不幸的是冒号字符用于格式化,所以我需要以某种方式对其进行转义 例如:在使用kwargs时,如何在Python format()中转义冒号?,python,string-formatting,Python,String Formatting,我想打印一本带冒号的字典。不幸的是冒号字符用于格式化,所以我需要以某种方式对其进行转义 例如: >>> d = {'hello': 'world', 'with:colon': 'moo'} >>> '{hello}'.format(**d) 'world' >>> '{with:colon}'.format(**d) KeyError: 'with' >>> '{with\:colon}'.format(**d) K
>>> d = {'hello': 'world', 'with:colon': 'moo'}
>>> '{hello}'.format(**d)
'world'
>>> '{with:colon}'.format(**d)
KeyError: 'with'
>>> '{with\:colon}'.format(**d)
KeyError: 'with\\'
>>> '{with::colon}'.format(**d)
KeyError: 'with'
据我所知,你所要求的是根本不可能的。具体来说,
由于arg_name不以引号分隔,因此无法在格式字符串中指定任意字典键(例如字符串'10'
或':-]'
)
不能这样做-键必须在语法上等同于Python标识符。请参见文档中的:
replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name ::= arg_name ("." attribute_name | "[" element_index "]")*
arg_name ::= [identifier | integer]
attribute_name ::= identifier
class QuotableFormatter(string.Formatter):
def __init__(self):
self.super = super(QuotableFormatter, self)
self.super.__init__()
self.quotes = {}
def parse(self, format_string):
fs = ''
for p in re.findall(r'(?:".+?")|(?:[^"]+)', format_string):
if p[0] == '"':
key = '_q_' + str(len(self.quotes))
self.quotes[key] = p[1:-1]
fs += key
else:
fs += p
return self.super.parse(fs)
def get_field(self, field_name, args, kwargs):
if field_name.startswith('_q_'):
field_name = self.quotes[field_name]
return self.super.get_field(field_name, args, kwargs)
正如他在回答中指出的那样,这是不可能的
解决方法是用有效的密钥替换密钥:
d_sanitised = {key.replace(":", "-"): value for key, value in d.items()}
当然,如果可能与其他键发生冲突,您可能需要小心
>>> d = {'hello': 'world', 'with:colon': 'moo'}
>>> d_sanitised = {key.replace(":", "-"): value for key, value in d.items()}
>>> '{with-colon}'.format(**d_sanitised)
'moo'
显然,这假设您可以修改格式字符串以适应。理想情况下,只需修改两端以避免在一起使用冒号。作为一种解决方法:
>>> d = {'hello': 'world', 'with:colon': 'moo'}
>>> '{hello} {}'.format(d['with:colon'],**d)
'world moo'
>>> '{hello} {0}'.format(d['with:colon'],**d)
'world moo'
遗憾的是,内置格式化程序不允许这样做。一个明显的语法扩展是允许在必要时引用键。您的格式字符串如下所示:
format('{"with:colon"} and {hello}'
幸运的是,扩展格式化程序以提供这种语法似乎很容易,下面是一个POC实现:
replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name ::= arg_name ("." attribute_name | "[" element_index "]")*
arg_name ::= [identifier | integer]
attribute_name ::= identifier
class QuotableFormatter(string.Formatter):
def __init__(self):
self.super = super(QuotableFormatter, self)
self.super.__init__()
self.quotes = {}
def parse(self, format_string):
fs = ''
for p in re.findall(r'(?:".+?")|(?:[^"]+)', format_string):
if p[0] == '"':
key = '_q_' + str(len(self.quotes))
self.quotes[key] = p[1:-1]
fs += key
else:
fs += p
return self.super.parse(fs)
def get_field(self, field_name, args, kwargs):
if field_name.startswith('_q_'):
field_name = self.quotes[field_name]
return self.super.get_field(field_name, args, kwargs)
用法:
d = {'hello': 'world', 'with:colon': 'moo', "weird!r:~^20": 'hi'}
print QuotableFormatter().format('{"with:colon":*>20} and {hello} and {"weird!r:~^20"}', **d)
# *****************moo and world and hi
从python 3.6开始,您可以使用新的f字符串格式解决此问题:
>>> d = {'hello': 'world', 'with:colon': 'moo'}
>>> print(f"with:colon is equal to {d['with:colon']}")
with:colon is equal to moo
{'with!惊呼:某物}
无法取消显示机器人笑脸:-]
+1,很好的解决方案-不幸的是,它使语法变得笨拙,但如果这是OP代码中的常见问题,这是迄今为止最好的解决方案。@Lattyware:是的,也许转义会更好,如{with\:colon}
。