Как извлечь ключевые слова из строки формата Python?
Я хочу предоставить автоматическое форматирование строк в API, чтобы:
my_api("path/to/{self.category}/{self.name}", ...)
можно заменить значениями атрибутов, вызванных в строке форматирования.
Как извлечь аргументы ключевого слова из строки формата Python:
"non-keyword {keyword1} {{escaped brackets}} {} {keyword2}" => 'keyword1', 'keyword2'
4 ответов
можно использовать 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()
использует его внутренне). Эта функция возвращает первая часть of имя, которое будут искать в аргументах, переданных str.format()
, плюс генератор для остальной части поля.
генератор дает (is_attribute, name)
кортежи; is_attribute
истинно, если следующее имя должно рассматриваться как атрибут, 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}
демо:
>>> 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.
Если все заполнители названы, специальный словарь может использоваться для перехвата, какие ключи пытаются получить доступ и войти в массив.
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
обратите внимание, что если есть неназванные заполнители, IndexError будет вызван .format()
(индекс кортежа вне диапазона).
построение ответа Martijn, более простой формат для полного списка, который я использовал:
>>> yourstring = "path/to/{self.category}/{self.name}"
>>> [x[1] for x in yourstring._formatter_parser() if x[1]]
['self.category', 'self.name']
это функционально точно так же, просто намного легче переварить.
можно сделать "path/to/{self.category}/{self.name}".format(self=self)
. Таким образом, вы могли бы работать с этими кваргами в __getattr__
.