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

为什么要学习 localsglobals?为了学习基于字典的字符串格式化。回想一下,常规字符串格式化 提供了一种将值插入字符串的简单方法。值列在一个元组中,并按顺序插入到字符串中每个格式标记的位置。虽然这很有效,但它并不总是最容易阅读的代码,尤其是在插入多个值时。您不能简单地一次性浏览字符串并理解结果是什么;您需要不断地在阅读字符串和阅读值元组之间切换。

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

示例 8.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 字典中的键,并用相应的值 secret 替换 %(pwd)s 标记。
2 基于字典的字符串格式化适用于任意数量的命名键。每个键都必须存在于给定的字典中,否则格式化将失败并出现 KeyError 错误。
3 您甚至可以两次指定同一个键;每次出现都将替换为相同的值。

那么为什么要使用基于字典的字符串格式化呢?好吧,为了在下一行进行字符串格式化而设置键和值字典似乎有点小题大做;当您碰巧已经有一个包含有意义的键和值的字典时,它才真正有用。比如 locals

示例 8.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-->'

示例 8.15. 更多基于字典的字符串格式化

    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, 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 会构建 局部命名空间的副本。