为了回答这个问题,您需要定义“优雅”。有几个因素值得考虑:
- 代码简短,易于记忆,易于编写和自我解释?
- 它是否重用底层逻辑(即遵循DRY原则)?
- 它是否实现了完全相同的解析逻辑?
不幸的是,字符串的“%”格式是在stringojbect.c中的C例程“PyString_Format”中实现的。此例程不提供允许访问格式字符串的已分析格式的API或挂钩。它只是在解析格式字符串时生成结果。因此,任何解决方案都需要复制C例程中的解析逻辑。这意味着DRY没有被遵循,并且如果对格式化规范进行了更改,则会暴露任何解决方案。
PyString_Format中的解析算法包含一定的复杂性,包括处理键名中的嵌套圆括号,所以不能使用正则表达式完全实现,也不能使用字符串“split()”。由于没有从PyString_Format复制C代码并将其转换为Python代码,我没有看到任何远程简单的方法,在所有的情况下正确提取映射密钥的名称。
所以我的结论是,没有“优雅”的方式来获取Python 2.7“%”格式字符串的映射关键字的名称。
以下代码使用正则表达式来提供覆盖最常见的用法的部分解决方案:
import re
class StringFormattingParser(object):
__matcher = re.compile(r'(?<!%)%\(([^)]+)\)[-# +0-9.hlL]*[diouxXeEfFgGcrs]')
@classmethod
def getKeyNames(klass, formatString):
return klass.__matcher.findall(formatString)
# Demonstration of use with some sample format strings
for value in [
'%(a)s and %(b)s are friends.',
'%%(nomatch)i',
'%%',
'Another %(matched)+4.5f%d%% example',
'(%(should_match(but does not))s',
]:
print StringFormattingParser.getKeyNames(value)
# Note the following prints out "really does match"!
print '%(should_match(but does not))s' % {'should_match(but does not)': 'really does match'}
P.S. DRY =不要重复自己(https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
您所描述的方法似乎效果不错。它返回['a','b']。那么现在失去了什么? –
@AdiLevin第一种方式需要额外的导入。第二种方式需要另一种字符串格式。我只是很好奇,有没有一种方法可以只使用'string'对象的内部方法和属性或者可能是一些字符串模块函数来获得相同的结果。 – hackprime
是什么阻止你使用'format()进行格式化?这看起来就像是其中一个更强大的案例。 – Joost