10.7. 全部放在一起
Description: Python from novice to pro
Keywords: Python, Dive Into Python, tutorial, object-oriented, programming, documentation, book, free

# 深入 Python :Dive Into Python 中文版 Python 从新手到专家 [Dip_5.4b_CPyUG_Release] | Find:

## 10.7. 全部放在一起

你已经了解很多基础的东西。让我们回来看看所有片段是如何整合到一起的。

作为开始，这里是一个接收命令行参数的脚本，它使用 `getopt` 模块。

    def main(argv):
    ...
        try:
            opts, args = getopt.getopt(argv, "hg:d", ["help", "grammar="])
        except getopt.GetoptError:
    ...
        for opt, arg in opts:
    ...

创建 `KantGenerator` 类的一个实例，然后将语法文件和源文件传给它，可能在命令行没有指定。

        k = KantGenerator(grammar, source)

`KantGenerator` 实例自动加载语法，它是一个 XML 文件。你使用自定义的 `openAnything` 函数打开这个文件 (可能保存在一个本地文件中或者一个远程服务器上)，然后使用内置的 `minidom` 解析函数将 XML 解析为一棵 Python 对象树。

        def _load(self, source):
            sock = toolbox.openAnything(source)
            xmldoc = minidom.parse(sock).documentElement
            sock.close()

哦，根据这种方式，你将使用到 XML 文档结构的知识建立一个引用的小缓冲，这些引用都只是 XML 文档中的元素。

        def loadGrammar(self, grammar):
            for ref in self.grammar.getElementsByTagName("ref"):
                self.refs[ref.attributes["id"].value] = ref

如果你在命令行中指定了某些源材料，你可以使用它；否则你将打开语法文件查找“顶层”引用 (没有被其它的东西引用) 并把它作为开始点。

        def getDefaultSource(self):
            xrefs = {}
            for xref in self.grammar.getElementsByTagName("xref"):
                xrefs[xref.attributes["id"].value] = 1
            xrefs = xrefs.keys()
            standaloneXrefs = [e for e in self.refs.keys() if e not in xrefs]
            return '<xref id="%s"/>' % random.choice(standaloneXrefs)

现在你打开了了源材料。它是一个 XML，你每次解析一个节点。为了让代码分离并具备更高的可维护性，你可以使用针对每个节点类型的独立处理方法。

        def parse_Element(self, node):
            handlerMethod = getattr(self, "do_%s" % node.tagName)
            handlerMethod(node)

你在语法里面跳来跳去，解析每一个 `p` 元素的所有孩子，

        def do_p(self, node):
    ...
            if doit:
                for child in node.childNodes: self.parse(child)

用任意一个孩子替换 `choice` 元素，

        def do_choice(self, node):
            self.parse(self.randomChildElement(node))

并用对应 `ref` 元素的任意孩子替换 `xref`，前面你已经进行了缓冲。

        def do_xref(self, node):
            id = node.attributes["id"].value
            self.parse(self.randomChildElement(self.refs[id]))

就这样一直解析，最后得到普通文本。

        def parse_Text(self, node):
            text = node.data
    ...
                self.pieces.append(text)

把结果打印出来。

    def main(argv):
    ...
        k = KantGenerator(grammar, source)
        print k.output()