如何从Python格式字符串中提取关键字?

Jac*_*ing 17 python string string-formatting

我想在API中提供自动字符串格式,以便:

my_api("path/to/{self.category}/{self.name}", ...)
Run Code Online (Sandbox Code Playgroud)

可以用格式化字符串中调出的属性值替换.


如何从Python格式字符串中提取关键字参数:

"non-keyword {keyword1} {{escaped brackets}} {} {keyword2}" => 'keyword1', 'keyword2'
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 44

您可以使用string.Formatter()该类来解析字符串中的字段,Formatter.parse()方法如下:

from string import Formatter

fieldnames = [fname for _, fname, _, _ in Formatter().parse(yourstring) if fname]
Run Code Online (Sandbox Code Playgroud)

演示:

>>> from string import Formatter
>>> yourstring = "path/to/{self.category}/{self.name}"
>>> [fname for _, fname, _, _ in Formatter().parse(yourstring) if fname]
['self.category', 'self.name']
>>> yourstring = "non-keyword {keyword1} {{escaped brackets}} {} {keyword2}"
>>> [fname for _, fname, _, _ in Formatter().parse(yourstring) if fname]
['keyword1', 'keyword2']
Run Code Online (Sandbox Code Playgroud)

您可以进一步解析这些字段名称; 为此,您可以使用str._formatter_field_name_split()方法(Python 2)/ _string.formatter_field_name_split()函数(Python 3)(此内部实现细节未以其他方式公开; Formatter.get_field()在内部使用它).此函数返回名称的第一部分,即在传递给的参数中str.format()查找的部分,以及该字段其余部分的生成器.

发电机产生(is_attribute, name)元组; is_attribute如果将下一个名称视为属性,则为true;如果是要查找的项,则为false obj[name]:

try:
    # Python 3
    from _string import formatter_field_name_split
except ImportError:
    formatter_field_name_split = str._formatter_field_name_split
from string import Formatter

field_references = {formatter_field_name_split(fname)[0]
 for _, fname, _, _ in Formatter().parse(yourstring) if fname}
Run Code Online (Sandbox Code Playgroud)

演示:

>>> from string import Formatter
>>> from _string import formatter_field_name_split
>>> yourstring = "path/to/{self.category}/{self.name}"
>>> {formatter_field_name_split(fname)[0]
...  for _, fname, _, _ in Formatter().parse(yourstring) if fname}
{'self'}
Run Code Online (Sandbox Code Playgroud)

请注意,此函数是Formatter()类的内部实现细节的一部分,可以在不事先通知的情况下从Python更改或删除,甚至可能在其他Python实现中不可用.


Mac*_*ish 6

更新: _formatter_parser() 是一个私有方法,因此对于python >= 3.8或更早版本不再可用

根据 Martijn 的答案,我使用的综合列表的更简单格式是:

>>> yourstring = "path/to/{self.category}/{self.name}"
>>> [x[1] for x in yourstring._formatter_parser() if x[1]]
['self.category', 'self.name']
Run Code Online (Sandbox Code Playgroud)

它的功能完全相同,只是更容易消化。