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                   1
>>> method = 'buildConnectionString'      2
>>> getattr(object, method)               3
<function buildConnectionString at 010D6D74>
>>> print getattr(object, method).__doc__ 4
Build a connection string from a dictionary of parameters.

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

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

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

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

字典的 keys 函数没有文档字符串,所以它的 __doc__ 属性为 None。让人迷惑的是,如果你直接计算 __doc__ 属性,Python IDE什么都不打印,如果你只是考虑它,是有意义的,但是却没有用。

2

你可以通过把 __doc__ 属性同 None 值直接进行比较,验证文档字符串确实为 None。(使用SQL Server脚本的小伙们要注意:在Transact/SQL中,应该使用 IS NULL 而不是 = NULL 来比较一个空值。在Python中,没有特别的语法,你可以使用 == 就象任何其它的比较。)

3 使用 str 函数接收空值,然后返回它的字符串表示,'None'

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

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

例 2.27. ljust 方法介绍

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

ljust 用空格填充字符串到指定长度。help 函数就是用它用来生成两列输出数据,并且将所有在第二列的文档字符纵向对齐。

2

如果给定的长度小于字符串的长度,ljust 将简单地返回未变化的字符串。它决不会截断字符串。

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

例 2.28. 打印列表

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

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

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

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

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