Python中如何创建字符串模板的子类?

23

我无法找到一个很好的Python子类化string.Template的示例,即使我在文档中看到了多次提到这样做的引用。

网络上是否有任何示例?

我想要将$更改为其他字符,并可能更改标识符的正则表达式。


需要注意的是,你不应该尝试在Cython中实现这个。它行不通。我不确定原因。 - Josh Gibson
1个回答

33

来自Python文档

高级用法:您可以派生Template的子类,以自定义占位符语法、分隔符字符或用于解析模板字符串的整个正则表达式。为此,您可以覆盖这些类属性:

  • delimiter - 这是描述占位符引入分隔符的文字字符串。默认值为$。请注意,这不应该是一个正则表达式,因为实现将根据需要调用re.escape()。

  • idpattern - 这是描述非括号占位符模式的正则表达式(大括号将自动添加)。默认值是[_a-z][_a-z0-9]*的正则表达式。

示例:

from string import Template

class MyTemplate(Template):
    delimiter = '#'
    idpattern = r'[a-z][_a-z0-9]*'

>>> s = MyTemplate('#who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes $what'

在Python 3中:

版本 3.2 中新增。

或者,您可以通过覆盖类属性 pattern 来提供整个正则表达式模式。如果这样做,该值必须是一个具有四个命名捕获组的正则表达式对象。这些捕获组对应于上面给出的规则,以及无效占位符规则:

  • escaped - 此组匹配默认模式中的转义序列,例如 $$。
  • named - 此组匹配非括号包含的占位符名称;它不应在捕获组中包含分隔符。
  • braced - 此组匹配括号包含的占位符名称;它不应在捕获组中包括分隔符或大括号。
  • invalid - 此组匹配任何其他定界符模式(通常是单个定界符),并且它应该出现在正则表达式的最后。

示例:

from string import Template
import re

class TemplateClone(Template):
    delimiter = '$'
    pattern = r'''
    \$(?:
      (?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
    )
    '''

class TemplateAlternative(Template):
    delimiter = '[-'
    pattern = r'''
    \[-(?:
       (?P<escaped>-) |            # Expression [-- will become [-
       (?P<named>[^\[\]\n-]+)-\] | # -, [, ], and \n can't be used in names
       \b\B(?P<braced>) |          # Braced names disabled
       (?P<invalid>)               #
    )
    '''

>>> t = TemplateClone("$hi sir")
>>> t.substitute({"hi": "hello"})
'hello sir'

>>> ta = TemplateAlternative("[-hi-] sir")
>>> ta.substitute({"hi": "have a nice day"})
'have a nice day sir'
>>> ta = TemplateAlternative("[--[-hi-]-]")
>>> ta.substitute({"hi": "have a nice day"})
'[-have a nice day-]'

显然,也可以只省略正则表达式组中的任何一个:escapednamedbracedinvalid来禁用它。


你知道这是如何在后台发生的吗?换句话说,分隔符是如何被替换为 '#' 的? - slopeofhope
@slopeofhope 这对我来说听起来像是一个单独的问题。 - Seanny123

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接