Python String Template自定义分隔符失效问题咨询
这问题的核心藏在string.Template的实现细节里——它用一个预编译的正则表达式pattern来匹配模板中的分隔符,而这个正则的生成和复用逻辑决定了你的代码行为差异。
让我们逐个分析你的例子:
1. 子类直接定义delimiter生效的原因
当你写:
class MyTemplate(Template): delimiter = '#'
这个子类并没有继承父类Template的pattern属性(准确说,父类的pattern是类级别的,但子类自身没有这个属性)。当你实例化MyTemplate时,它的__init__方法会检查到self.pattern是None,于是用子类的delimiter='#'重新编译生成了对应的正则表达式,自然能正确匹配#key。
2. 直接修改Template.delimiter无效的原因
Template类在被定义的时候,就已经预先编译好了基于默认$分隔符的pattern正则。当你修改Template.delimiter='#'时,这个已经存在的pattern并不会自动更新——实例化Template时,__init__发现类已经有现成的pattern,就直接复用它,完全不会理会你修改后的delimiter,所以代码还是在找$key而非#key。
3. 子类用类方法修改delimiter无效的原因
你的MyTemplate子类默认继承了父类Template预编译好的、基于$的pattern。当你调用MyTemplate.setDelim('#')修改子类的delimiter时,子类的pattern依然是之前继承来的旧正则。实例化时__init__看到self.pattern不为None,就不会重新生成新的正则,所以还是按旧规则匹配,自然无法识别#key。
解决方法:修改分隔符后重置pattern
要让修改delimiter生效,必须同时把对应的pattern设为None,这样__init__才会重新编译新的正则:
修复第二个例子:
from string import Template Template.delimiter = '#' Template.pattern = None # 重置pattern,触发重新编译 d = {'key':'value'} t = Template('key is #key') print(t.substitute(d)) # 现在输出"key is value"
修复第三个例子:
from string import Template class MyTemplate(Template): @classmethod def setDelim(cls, delim): cls.delimiter = delim cls.pattern = None # 重置pattern MyTemplate.setDelim('#') d = {'key':'value'} t = MyTemplate('key is #key') print(t.substitute(d)) # 生效,输出"key is value"
简单来说,Template的pattern是类级别的缓存,用来避免重复编译正则提升性能,但这也意味着修改分隔符后必须手动清空缓存,才能让新的分隔符生效。
内容的提问来源于stack exchange,提问作者BluePlateSpecial

