4.6. 基于字典的字符串格式化

字符串格式化 提供了一种将值插入字符串中的一种便捷的方法。值被列在一个元组(tuple)中,按照顺序插入到字符串中每个格式化标记所在的位置上。尽管这种做法效率高,但还不是最容易阅读的代码,特别是当插入多个值的时候。仅用眼看一遍字符串,你不能马上就明白结果是什么;你需要经常地在字符串和值的元组之间进行反复查看。

有另外一种字符串格式化的形式,它使用字典而不是值的元组。

例 4.13. 基于字典的字符串格式化介绍

>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> "%(pwd)s" % params                                    1
'secret'
>>> "%(pwd)s is not a good password for %(uid)s" % params 2
'secret is not a good password for sa'
>>> "%(database)s of mind, %(database)s of body" % params 3
'master of mind, master of body'
1 这种字符串格式化形式不用显示的值的元组,而是使用一个字典,params。并且标记也不是在字符串中的一个简单 %s,而是包含了一个用括号包围起来的名字。这个名字是 params 字典中的一个键字,并且将 %(pwd)s 标记所在的地方替换成相应的值 secret
2 基于字典的字符串格式化可用于任意数量的有名的键字。每个键字必须在一个给定的字典中存在,否则这个格式化操作将失败并引发一个 KeyError 的异常。
3 你甚至可以两次指定同一键字,每个键字发生之处将被同一个值所替换。

那么为什么你偏要使用基于字典的字符串格式化呢?好,在下面一行中,仅为了进行字符串格式化就需要创建一个有键字和值的字典看上去的确有些小题大作。它的真正最大用处是当你碰巧已经有了象 locals 一样的有意义的键字和值的字典的时候。

例 4.14. 在 BaseHTMLProcessor.py 中的基于字典的字符串格式化

    def handle_comment(self, text):        
        self.pieces.append("<!--%(text)s-->" % locals()) 1
1 使用内置的 locals 函数是最普通的基于字典的字符串格式化的应用。这就是说你可以在你的字符串(本例中是 text,它作为一个参数传递给类方法)中使用局部变量的名字,并且每个命名的变量将会被它的值替换。如果 text'Begin page footer',字符串格式化 "<!--%(text)s-->" % locals() 将得到字符串 '<!--Begin page footer-->'
    def unknown_starttag(self, tag, attrs):
        strattrs = "".join([' %s="%s"' % (key, value) for key, value in attrs]) 1
        self.pieces.append("<%(tag)s%(strattrs)s>" % locals())                              2
1 当这个模块被调用时,attrs 是一个键/值元组的列表,就象一个字典的 items。这就意味着我们可以使用多变量赋值来遍历它。到现在这将是一种熟悉的模式,但是这里有很多东西,让我们分开来看:
  1. 假设 attrs[('href', 'index.html'), ('title', 'Go to home page')]
  2. 在这个列表理解的第一轮循环中,key 将为 'href'value 将为 'index.html'
  3. 字符串格式化 ' %s="%s"' % (key, cgi.escape(value)) 将生成 ' href="index.html"'。这个字符串就作为这个列表理解返回值的第一个元素。
  4. 在第二轮中,key 将为 'title'value 将为 'Go to home page'
  5. 字符串格式化将生成 ' title="Go to home page"'
  6. 这个列表理解返回两个生成的字符串列表,并且 strattrs 将把这个列表的两个元素连接在一起形成 ' href="index.html" title="Go to home page"'
2 现在,使用基于字典的字符串格式化,我们将 tagstrattrs 的值插入到一个字符串中。所以,如果 tag'a',最终的结果会是 '<a href="index.html" title="Go to home page">',并且这就是追加到 self.pieces 后面的东西。
Important
使用 locals 来应用基于字典的字符串格式化是一种方便的作法,它可以使复杂的字符串格式化表达式更易读。但它需要花费一定的代价。在调用 locals 方面有一点性能上的问题,这是由于 locals 创建了局部名字空间的一个拷贝引起的。