本节书摘来自异步社区《Python Cookbook(第2版)中文版》一书中的第1章,第1.17节,作者[美]Alex Martelli , Anna Martelli Ravenscrof , David Ascher ,高铁军 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。
1.17 替换字符串中的子串—Python 2.4
任务
在Python 2.4的环境下,你想完成这样的任务:给定一个字符串,通过查询一个字符串替换字典,将字符串中被标记的子字符串替换掉。
解决方案
Python 2.4提供了一个新的string.Template类,可以应用于这个任务。下面给出一段代码以展示怎样使用这个类:
import string
# 从字符串生成模板,其中标识符被$标记
new_style = string.Template('this is $thing')
# 给模板的substitute方法传入一个字典参数并调用之
print new_style.substitute({'thing':5}) # 输出:this is 5
print new_style.substitute({'thing':'test'}) # 输出:this is test
# 另外,也可以给substitute方法传递关键字参数
print new_style.substitute(thing=5) # 输出:this is 5
print new_style.substitute(thing='test') # 输出:this is test
讨论
Python 2.3中,用于标记—替换的字符串格式被写为更加繁琐的形式:
old_style = 'this is %(thing)s'
标识符被放在一对括弧中,括弧前面一个%,后面一个s。然后,还需要使用%操作符,使用的格式是将需要处理的字符串放在%操作符左边并在右边放上字典:
print old_style % {'thing':5} # emits: this is 5
print old_style % {'thing':'test'} # emits: this is test
当然,这样的代码在Python 2.4中也可以正常工作。不过,新的string.Template提供了一个更简单的替代方法。
当你创建string.Template实例时,在字符串格式中,可以用两个美元符($)来代表$,还可以让那些需要被替换的标识后面直接跟上用于替换的文本或者数字,并用一对花括号({ })将它们括起来。下面是一个例子:
form_letter = '''Dear $customer,
I hope you are having a great time.
If you do not find Room $room to your satisfaction,
let us know. Please accept this $$5 coupon.
Sincerely,
$manager
${name}Inn'''
letter_template = string.Template(form_letter)
print letter_template.substitute({'name':'Sleepy', 'customer':'Fred Smith',
'manager':'Barney Mills','room':307,
})
上面的代码片段给出下列输出:
Dear Fred Smith,
I hope you are having a great time.
If you do not find Room 307 to your satisfaction,
let us know. Please accept this $5 coupon.
Sincerely,
Barney Mills
SleepyInn
有时,为了给substitute准备一个字典做参数,最简单的方法是设定一些本地变量,然后将所有这些变量交给locals()(此函数将创建一个字典,字典的key就是本地变量,本地变量的值可通过key来访问):
msg = string.Template('the square of $number is $square')
for number in range(10):
square = number * number
print msg.substitute(locals( ))
另一个简单的办法是使用关键字参数语法而非字典,直接将值传递给substitute:
msg = string.Template('the square of $number is $square')
for i in range(10):
print msg.substitute(number=i, square=i*i)
甚至可以同时传递字典和关键字参数:
msg = string.Template('the square of $number is $square')
for number in range(10):
print msg.substitute(locals( ), square=number*number)
为了防止字典的条目和关键字参数显式传递的值发生冲突,关键字参数优先。比如:
msg = string.Template('an $adj $msg')
adj = 'interesting'
print msg.substitute(locals( ), msg='message')
# emits an interesting message