Chapter 4. 内省の力

この章では Python の強みの 1 つ, 内省 (introspection) を扱います. 知っての通り Python の全てはオブジェクトで, 内省とはオブジェクトとしてメモリに納まっている他のモジュールや関数を見たり, その情報を取ったり, 操作したりするコードのことです. そのうちあなたは, 名前の無い関数を定義したり, 引数の順序を入れ替えて関数を呼び出したり, 前以ては名前すら知らない関数を参照したりするようになります.

4.1. 飛び込む

以下は完全な動く Python プログラムです. あなたはプログラムの大部分を見ただけで理解できるはずです. 番号が付いている行はChapter 2, 初めての Python プログラムで扱った内容を示しています. 残りのコードが怖く思えても心配しないでください. この章を通してそれら全てについて学びます.

Example 4.1. apihelper.py

もしまだダウンロードしていないのなら, 良かったらこの本で使われているこの例や他の例をダウンロードしてみてください.


def info(object, spacing=10, collapse=1): 1 2 3
    """Print methods and doc strings.
    
    Takes module, class, list, dictionary, or string."""
    methodList = [method for method in dir(object) if callable(getattr(object, method))]
    processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
    print "\n".join(["%s %s" %
                      (method.ljust(spacing),
                       processFunc(str(getattr(object, method).__doc__)))
                     for method in methodList])

if __name__ == "__main__":                4 5
    print info.__doc__
1 このモジュールには 1 つの関数 info があります. その関数宣言によると, 3 つのパラメータ object, spacing, collapse を引数に取ります. じきに分かりますが, 後ろ 2 つは実はオプション引数なのです.
2 info 関数には関数の目的が簡潔に書かれた複数行の doc string があります. 返り値について述べられていないことに注意してください. この関数は値を返すのではなく副作用を発生させるために単独で使われます.
3 関数内部のコードはインデント付けされています.
4 if __name__ トリックのおかげで, 他のプログラムからのモジュールとしての使い勝手に影響を与えることなく, 自身をプログラムとして実行して何か有益なことができます. この例では, プログラムは単に info 関数の doc string を出力しているだけです.
5 if== を比較に使っていて, 丸括弧は必要ではありません.

info 関数は, プログラマであるあなたが Python IDE で作業をしているときに使えるように設計されています. 引数には関数やメソッドを持つ任意のオブジェクト (関数を持つモジュールやメソッドを持つリストなど) を取り, その関数と doc string を出力します.

Example 4.2. apihelper.py の使用例

>>> from apihelper import info
>>> li = []
>>> info(li)
append     L.append(object) -- append object to end
count      L.count(value) -> integer -- return number of occurrences of value
extend     L.extend(list) -- extend list by appending list elements
index      L.index(value) -> integer -- return index of first occurrence of value
insert     L.insert(index, object) -- insert object before index
pop        L.pop([index]) -> item -- remove and return item at index (default last)
remove     L.remove(value) -- remove first occurrence of value
reverse    L.reverse() -- reverse *IN PLACE*
sort       L.sort([cmpfunc]) -- sort *IN PLACE*; if given, cmpfunc(x, y) -> -1, 0, 1

デフォルトでは出力は読みやすい形式になっています. 複数行の doc string は長い 1 行に折り畳まれていますが, このオプションは collapse 引数に 0 を指定することで変更できます. もし関数名が 10 文字よりも長いなら, spacing 引数により大きな値を指定して出力を読みやすくすることができます.

Example 4.3. apihelper.py の進んだ使い方

>>> import odbchelper
>>> info(odbchelper)
buildConnectionString Build a connection string from a dictionary Returns string.
>>> info(odbchelper, 30)
buildConnectionString          Build a connection string from a dictionary Returns string.
>>> info(odbchelper, 30, 0)
buildConnectionString          Build a connection string from a dictionary
    
    Returns string.