Get keys from template

后端 未结 7 933
忘掉有多难
忘掉有多难 2021-01-04 06:56

I would like to get a list of all possible keyword arguments a string template might use in a substitution.

Is there a way to do this other than re?

相关标签:
7条回答
  • 2021-01-04 07:07
    >>> import string
    >>> get_keys = lambda s:[el.strip(string.punctuation) 
                             for el in s.split()if el.startswith('$')]
    >>> get_keys("$one is a $lonely $number.")
    ['one', 'lonely', 'number']
    
    0 讨论(0)
  • 2021-01-04 07:11

    try str.strip() along with str.split():

    In [54]: import string
    
    In [55]: text="$one is a $lonely $number."
    
    In [56]: [x.strip(string.punctuation) for x in text.split() if x.startswith("$")]
    Out[56]: ['one', 'lonely', 'number']
    
    0 讨论(0)
  • 2021-01-04 07:13

    You could render it once with an instrumented dictionary which records calls, or a defaultdict, and then check what it asked for.

    from collections import defaultdict
    d = defaultdict("bogus")
    text%d
    keys = d.keys()
    
    0 讨论(0)
  • 2021-01-04 07:16

    You could try:

    def get_keys(s):
        tokens = filter(lambda x: x[0] == "$", s.split())
        return map(lambda x: x[1:], tokens)
    
    0 讨论(0)
  • 2021-01-04 07:17

    The string.Template class has the pattern that is uses as an attribute. You can print the pattern to get the matching groups

    >>> print string.Template.pattern.pattern
    
        \$(?:
          (?P<escaped>\$) |   # Escape sequence of two delimiters
          (?P<named>[_a-z][_a-z0-9]*)      |   # delimiter and a Python identifier
          {(?P<braced>[_a-z][_a-z0-9]*)}   |   # delimiter and a braced identifier
          (?P<invalid>)              # Other ill-formed delimiter exprs
        )
    

    And for your example,

    >>> string.Template.pattern.findall("$one is a $lonely $number.")
    [('', 'one', '', ''), ('', 'lonely', '', ''), ('', 'number', '', '')]
    

    As you can see above, if you do ${one} with braces it will go to the third place of the resulting tuple:

    >>> string.Template.pattern.findall('${one} is a $lonely $number.')
    [('', '', 'one', ''), ('', 'lonely', '', ''), ('', 'number', '', '')]
    

    So if you want to get all the keys, you'll have to do something like:

    >>> [s[1] or s[2] for s in string.Template.pattern.findall('${one} is a $lonely $number.$$') if s[1] or s[2]]
    ['one', 'lonely', 'number']
    
    0 讨论(0)
  • 2021-01-04 07:29

    If it's okay to use string.format, consider using built-in class string.Formatter which has a parse() method:

    >>> from string import Formatter
    >>> [i[1] for i in Formatter().parse('Hello {1} {foo}')  if i[1] is not None]
    ['1', 'foo']
    

    See here for more details.

    0 讨论(0)
提交回复
热议问题