<< >>

diveintopython.org |

Python for experienced programmers

## 2.9. 全部放在一起

最一行代码，是唯一我们还没有解析过的，它完成全部的工作。过目前为止，很顺利，因为我们需要的每件事都已经按照需求建立好了。所有的多米诺骨牌已经就位，到了将它们推倒的时候了。

例 2.24. `apihelper.py` 的内容

        print "\n".join(["%s %s" %
                          (method.ljust(spacing),
                           processFunc(str(getattr(object, method).__doc__))
                         for method in methodList])

注意这是一条命令，分割成多行，但是没有使用续行符(“\”)。还记得我说过一些表达式可以分割成多行不需要使用反斜线吗？列表映射就是这些表达式之一，因为整个表达式包括在方括号里。

现在，让我们从后向前分析。

    for method in methodList

告诉我们这是一个列表映射。如你所知，`methodList` 是一个在`object` 中所有我们关心的方法的列表。那么我们用 `method` 来遍历列表。

例 2.25. 动态得到文档字符串

    >>> import odbchelper
    >>> object = odbchelper
    >>> method = 'buildConnectionString'
    >>> getattr(object, method)
    <function buildConnectionString at 010D6D74>
    >>> print getattr(object, method).__doc__
    Build a connection string from a dictionary of parameters.

        Returns string.

| 在 `help` 函数中，`object` 是我们正要得到帮助的对象，它被作为一个参数传进来。
| 当我们遍历 `methodList`，`method` 是当前方法的名字。
| 通过使用 `getattr` 函数，我们得到在 `object` 模块中对于 `method` 函数的一个引用。
| 现在，打印出方法的文档字符串很容易。

接下来的困惑是在文档字符串周围 `str` 的使用。你可能回忆得起， `str` 是一个内置的函数，它可以强制将数据转化为字符串。但是一个文档字符串已经是字符串了，那么为什么还要费事地使用 `str` 函数呢？答案就是：不是每个函数都有文档字符串，那么如果没有，它的 `__doc__` 属性为 `None`。

例 2.26. 为什么对一个文档字符串使用 `str` ？

    >>> {}.keys.__doc__
    >>> {}.keys.__doc__ == None
    1
    >>> str({}.keys.__doc__)
    'None'

| 字典的 `keys` 函数没有文档字符串，所以它的 `__doc__` 属性为 `None`。让人迷惑的是，如果你直接计算 `__doc__` 属性，Python IDE什么都不打印，如果你只是考虑它，是有意义的，但是却没有用。
| 你可以通过把 `__doc__` 属性同 `None` 值直接进行比较，验证文档字符串确实为 `None`。(使用SQL Server脚本的小伙们要注意：在Transact/SQL中，应该使用 `IS NULL` 而不是 `= NULL` 来比较一个空值。在Python中，没有特别的语法，你可以使用 == 就象任何其它的比较。)
| 使用 `str` 函数接收空值，然后返回它的字符串表示，`'None'`。

现在我们保证有了一个字符串，我们可以传递这个字符串给 `processFunc`，这个函数我们定义为一个要不压缩空白要不不压缩的函数。现在你明白了为什么用 `str` 将一个 `None` 值转换成一个字符串表达的重要性了吧。`processFunc` 假定一个字符串参数，并且调用它的 `split` 方法，如果我们传给 `split` 方法 `None` ，则这个函数会失败，因为 `None` 没有一个 `split` 方法。

往回再深一步，我们看到再一次使用了字符串格式化来连接 `processFunc` 的返回值和 `method` 的 `ljust` 方法的返回值。`ljust` 方法是一个我们以前没见过的字符串方法。

例 2.27. `ljust` 方法介绍

    >>> s = 'buildConnectionString'
    >>> s.ljust(30)
    'buildConnectionString         '
    >>> s.ljust(20)
    'buildConnectionString'

| `ljust` 用空格填充字符串到指定长度。`help` 函数就是用它用来生成两列输出数据，并且将所有在第二列的文档字符纵向对齐。
| 如果给定的长度小于字符串的长度，`ljust` 将简单地返回未变化的字符串。它决不会截断字符串。

我们就快完成了。有了从 `ljust` 方法得到的填充过的方法名字和从调用 `processFunc` 得到的文档字符串(可能压缩过)，我们将两者连接起来，然后得到单一字符串。因为我们对 `methodList` 进行映射，最后得到一个字符串列表。使用 `"\n"` 字符串的 `join` 方法，我们将这个列表连接成单一字符串，列表中每一个元素独占一行，接着打印出结果。

例 2.28. 打印列表

    >>> li = ['a', 'b', 'c']
    >>> print "\n".join(li)
    a
    b
    c

| 当你处理列表时，这的确是一个有用的调试技巧。并且在Python中，你几乎总是在操纵列表。

这就是最后一个问题。这个代码现在应该相当清楚了。

例 2.29. 重新回顾 `apihelper.py` 的内容

        print "\n".join(["%s %s" %
                          (method.ljust(spacing),
                           processFunc(str(getattr(object, method).__doc__))
                         for method in methodList])

« 使用 lambda 函数 | 小结 »