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

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

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

my_api("path/to/{self.category}/{self.name}", ...)

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


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

"non-keyword {keyword1} {{escaped brackets}} {} {keyword2}" => 'keyword1', 'keyword2'
python string string-formatting
4个回答
69
投票

您可以使用

string.Formatter()
来解析字符串中的字段,并使用
Formatter.parse()
方法
:

from string import Formatter

fieldnames = [fname for _, fname, _, _ in Formatter().parse(yourstring) if fname]

演示:

>>> 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']

您可以进一步解析这些字段名称;为此,您可以使用

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;如果它是要使用
obj[name]
查找的项目,则为 false:

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}

演示:

>>> 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'}

请考虑到此函数是

Formatter()
类的内部实现细节的一部分,可以在不通知的情况下从 Python 中更改或删除,甚至可能在其他 Python 实现中不可用。


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']
它的功能完全相同,只是更容易消化。


3
投票
如果所有占位符都被命名,则可以使用特殊字典来拦截尝试访问哪些键并将其记录到数组中。

def format_keys(str_): class HelperDict(dict): def __init__(self): self._keys = [] def __getitem__(self, key): self._keys.append(key) d = HelperDict() str_.format_map(d) return d._keys

请注意,如果存在未命名的占位符,

.format()

(元组索引超出范围)将引发 IndexError。


0
投票
你可以做

"path/to/{self.category}/{self.name}".format(self=self)

。因此,您可以在 
__getattr__
 中使用那些 kwargs。

© www.soinside.com 2019 - 2024. All rights reserved.