python - how to enumerate string placeholders? -


i'd know what's best way enumerate placeholders strings, i've seen there post asks how-can-i-find-all-placeholders-for-str-format-in-a-python-string-using-a-regex i'm not sure answers provided giving me i'm looking for, let's examine little test:

import string  tests = [     ['this placeholder 1 {} , 2 {}', 2],     ['another placeholder here {} , here \"{}\"', 2] ] s in tests:     num_placeholders = len([         name text, name, spec, conv in string.formatter().parse(s[0])])     if num_placeholders != s[1]:         print("fail: {0} has {1} placeholders!!! excepted result {2}".format(             s[0], num_placeholders, s[1])) 

it seems string.formatter not giving me expected answer i'm looking for:

fail: placeholder here {} , here "{}" has 3 placeholders!!! excepted result 2 

because ignoring other elements on tuple parse(s) returns:

>>> import string >>>  >>> tests = [ ...     "{} spam eggs {}", ...     "{0} spam eggs {1}", ...     "{0:0.2f} spam eggs {1:0.2f}", ...     "{{1}} spam eggs {{2}}" ... ] >>> s in tests: ...     print [x x in string.formatter().parse(s)] ...  [('', '', '', none), (' spam eggs ', '', '', none)] [('', '0', '', none), (' spam eggs ', '1', '', none)] [('', '0', '0.2f', none), (' spam eggs ', '1', '0.2f', none)] [('{', none, none, none), ('1}', none, none, none), (' spam eggs {', none, none, none), ('2}', none, none, none)] 

edit: see mean now. yes, interpretation of parsing not intuitive nor obvious. length of returned list not count of placeholders count of literal portions of strings, including empty string @ start not including empty string @ end. , each element contains format of follows. example:

>>> list(string.formatter().parse('{}')) [('', '', '', none)] 

this base case, , there 1 single empty string of literal text. there 2 empty strings, parser not include last empty string.

>>> list(string.formatter().parse('a {}')) [('a ', '', '', none)] 

now have same before: 1 literal string "a " nothing follows. since there nothing follows format bracket there no element.

>>> list(string.formatter().parse('{} b')) [('', '', '', none), (' b', none, none, none)] 

this interesting case: since format bracket @ start, first literal string empty literal string, , follows string " b".

>>> list(string.formatter().parse('a {1} b {2} c')) [('a ', '1', '', none), (' b ', '2', '', none), (' c', none, none, none)] 

this 1 complete example. have 3 literal string pieces: ['a ', ' b ', ' c']. confusing part specific format information format brackets {} merged previous literal string element.

edit2:

>>> [x[0] x in string.formatter().parse('another placeholder here {} , here \"{}\"')] ['another placeholder here ', ' , here "', '"'] 

we follow same logic here. quotes raw literal string, can change quotes else:

>>> [x[0] x in string.formatter().parse('another placeholder here {} , here qqq{}www')] ['another placeholder here ', ' , here qqq', 'www'] 

if consider 'name' each returned tuple literal string. between each individual element lies format placeholder.

you need understand result of parse() point of view of formatting string. result makes simple produce output formatted string. example:

>>> [x x in string.formatter().parse('a{}')] [('a', '', '', none)] >>> [x x in string.formatter().parse('a')] [('a', none, none, none)] 

with logic can count number of placeholders in format string this:

>>> def count_placeholders(fmt): ...     count = 0 ...     l = string.formatter().parse(fmt) ...     x in l: ...         if x[1] not none: ...             count += 1 ...     return count ...  >>> count_placeholders('') 0 >>> count_placeholders('{}') 1 >>> count_placeholders('{}{}') 2 >>> count_placeholders('a {}{}') 2 >>> count_placeholders('a {} b {}') 2 >>> count_placeholders('a {} b {} c') 2 

Comments