27

I am formatting strings using named arguments with .format(). How can I obtain a list of arguments?

For example:

>>> my_string = 'I live in {city}, {state}, {country}.'
>>> get_format_args(my_string)
# ['city', 'state', 'country']

Note that order does not matter. I have dug a fair amount into the string.Formatter documentation to no avail. I am sure you could write regex to do this, but there must bet a more elegant way.

0

2 Answers 2

49

It looks like you can get field names using the Formatter.parse method:

>>> import string
>>> my_string = 'I live in {city}, {state}, {country}.'
>>> [tup[1] for tup in string.Formatter().parse(my_string) if tup[1] is not None]
['city', 'state', 'country']

This will also return non-named arguments. Example: "{foo}{1}{}" will return ['foo', '1', '']. But if necessary you can filter out the latter two by using str.isdigit() and comparing against the empty string respectively.

Sign up to request clarification or add additional context in comments.

1 Comment

It's also documented: string.Formatter.parse
5

Regex can solve your problem.

>>> import re 
>>> re.findall(r'{(.*?)}', 'I live in {city}, {state}, {country}.')
['city', 'state', 'country']

Edit:

To avoid matching escaped placeholders like '{{city}}' you should change your pattern to something like:

(?<=(?<!\{)\{)[^{}]*(?=\}(?!\}))

Explanation:

(?<=      # Assert that the following can be matched before the current position
 (?<!\{)  #  (only if the preceding character isn't a {)
\{        #  a {
)         # End of lookbehind
[^{}]*    # Match any number of characters except braces
(?=       # Assert that it's possible to match...
 \}       #  a }
 (?!\})   #  (only if there is not another } that follows)
)         # End of lookahead

3 Comments

This approach fails with escaped placeholders like '{{city}}'
I prefer this since it can easily be used to find specific arguments, like when '{x:03d}' is specified and I want to see if x is an argument
This won't work for nested {} like this example from the docs: '{0:{fill}{align}16}'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.