关于string.Template的简单介绍

一、简介

  string模块定义了一种新字符串类型Template,它简化了特定的字符串置换操作。

  何谓“简化”?我们可以先想一下我们之前比较常用的有关字符串的“置换”操作有哪些:一种是利用%操作符实现,另外一种是格式化字符串format实现。那么,相比于这两种方法,string.Template究竟简化在何处呢?

  那我们就以下面的代码为例简单说明一下string.Template的用法与上述两种方式的区别:

# -*- coding: utf-8  -*-
# -*- Author: WangHW -*-
import string

values = {'var':3.3333333}
#1
t1 = string.Template("""
Variable        : $var
Escape          : $$
Variable in text: ${var}iable
""")
print('TEMPLATE:',t1.substitute(values))
print('############################')
#2
s = """
Variable        : %(var)s
Escape          : %%
Variable in text: %(var)siable
"""
print('INTERPOLATION:',s % values)
print('############################')

#3
s1 = """
Variable         {var}
Escape          : {{}}
Variable in text: {var}iable
"""
print('FORMAT:',s1.format(**values))

结果如下:

  上面的代码分别利用string.Template方法、%操作符以及format方法进行了字符串的置换操作。这里我们可以看出string.Template是利用$符号进行“关联”,用substitute方法取值的

  这里直接给出结论:利用string.Template方法是不需要考虑参数的数据类型的!这是string.Template方法与后面两种方法最重要的不同之处。string.Template方法直接将参数转换为字符串格式,然后将转换后的字符串直接插入结果中去。没有可用的格式化选项供我们选择,例如,对于一个浮点数(如上述例子所示)来讲,我们没办法控制代表这个浮点数数值的位数。

二、safe_substitute方法

  上例中我们利用substitute取值。大家肯定会问了:如果$关联的字符串在前面定义的values中不存在怎么办?难道会报错吗?

  答案是肯定的!为了避免上述问题的产生我们利用safe_substitute方法取值,当然可以跟原生的substitute方法对比一下:

# -*- coding: utf-8  -*-
# -*- Author: WangHW -*-
import string

values = {'var':'foo'}

t = string.Template('$var is here but $missing is not provided')

try:
    print('substitute()     :',t.substitute(values))
except KeyError as err:
    print('ERROR:',str(err))

print('safe_substitute():',t.safe_substitute(values))

  结果如下:

  大家可以看到:values中并没有代表key的字符串'missing',而我们在Template中却试图利用$missing取其对应的值。因此substitute方法会报错,而safe_substitute方法可以巧妙的“避免”这个错误,保证程序的流畅性。

三、进阶:模块功能的“修改”

  在实际中,大家可能习惯利用%操作符去进行字符串的置换了,那么,如果我们既想利用string.Template方法的便捷性,又想按照自己的意愿与需求定义额外的功能,这就需要我们新定义一个继承自string.Template的类(例如命名为MyTempate),在这里修改其中的某些属性去满足我们的需求。

  下面代码中MyTemplate类继承自string.Template,修改了操作符delimiter与id模式idpattern,实现了利用%关联代表key的字符串,然后利用正则表达式使safe_substitute()只能匹配出带下划线的且由a-z组成的字符串:

# -*- coding: utf-8  -*-
# -*- Author: WangHW -*-
import string

class MyTemplate(string.Template):
    #操作符
    delimiter = '%'
    #id模式
    idpattern = '[a-z]+_[a-z]+'


if __name__ == '__main__':
    template_text = '''
    Delimiter : %%
    Replaced  : %with_underscore
    Ignored   : %notunderscored
    '''
    d = {
        'with_underscore':'replaced',
        'notunderscored':'not replaced'
    }

    t = MyTemplate(template_text)
    print('Modified ID pattern:')
    print(t.safe_substitute(d))

  结果如下:

  上例中,由于代表key的字符串‘notunderscored’没有下划线,没有匹配到,所以结果中只能得出%notunderscored,不能取到具体的值。

  需要注意的是:这种方法在实际中非常常用!在实际中我们需要根据具体的需求灵活的“更改”模块中某个对象的某个属性去实现具体的需求!

posted on 2018-06-27 00:18  江湖乄夜雨  阅读(6226)  评论(0编辑  收藏  举报