You are here: Home > Dive Into Python > 内省の力 > オブジェクトへの参照を getattr で取得する | << >> | ||||
Dive Into PythonPython from novice to pro |
すでにあなたは Python の関数はオブジェクトだということは知っています. まだ知らないのは, 実行時までに名前を知ることなく関数への参照を取得できる方法です. それは getattr 関数を使うことです.
>>> li = ["Larry", "Curly"] >>> li.pop <built-in method pop of list object at 010DF884> >>> getattr(li, "pop") <built-in method pop of list object at 010DF884> >>> getattr(li, "append")("Moe") >>> li ["Larry", "Curly", "Moe"] >>> getattr({}, "clear") <built-in method clear of dictionary object at 00F113D4> >>> getattr((), "pop") Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'tuple' object has no attribute 'pop'
リストの pop メソッドへの参照を取得します. これは pop メソッドの呼び出しではないことに注意してください. そっちは li.pop() です. これはメソッドそのものです. | |
これも pop メソッドへの参照を返しますが, 今回はメソッドの名前は予め分かっていて, getattr 関数に文字列引数として渡されています. getattr は非常に有用な組み込み関数で, 任意のオブジェクトの任意の属性を返します. この例では, オブジェクトはリストで属性は pop メソッドです. | |
ここまでの「非常に有用」程度では驚かないようなら, これをやってみてください. getattr の返り値はメソッドで, あたかも li.append("Moe") と直接呼ぶかのように呼び出せます. しかし関数を直接呼び出してはおらず, 代わりに名前という文字列で関数を特定しています. | |
getattr 関数は辞書にも使えます. | |
理論的には, getattr 関数はタプルにも使えますが, タプルはメソッドを持たないので, どんな属性名を与えても getattr は例外を送出します. |
getattr 関数は組み込みのデータ型のためだけのものではありません. モジュールにも使えます.
>>> import odbchelper >>> odbchelper.buildConnectionString <function buildConnectionString at 00D18DD4> >>> getattr(odbchelper, "buildConnectionString") <function buildConnectionString at 00D18DD4> >>> object = odbchelper >>> method = "buildConnectionString" >>> getattr(object, method) <function buildConnectionString at 00D18DD4> >>> type(getattr(object, method)) <type 'function'> >>> import types >>> type(getattr(object, method)) == types.FunctionType True >>> callable(getattr(object, method)) True
これは, Chapter 2, 初めての Python プログラムで学んだ odbchelper モジュールの buildConnectionString 関数への参照を返します. (ここで表示されている16進アドレスは私 (筆者 Mr. Mark Pilgrim) のマシンでの値です. あなたのマシンでの出力とは異なります.) | |
getattr を使うことで, 同じ関数への同じ参照が得られます. 一般的に, getattr(object, "attribute") は object.attribute と同等です. object にモジュールが来る場合は, attribute には, 関数やクラスやグローバル変数などのモジュールで定義されているものが入ります. | |
そしてこれが実際に info 関数の中で使っている形式です. object は引数として関数に渡され, method はメソッド名や関数名の文字列が渡されます. | |
この例では method は関数名で, type 関数を使うことでそれを確認できます. | |
method は関数なので, 呼び出し可能です. |
getattr はよくディスパッチャとして使われます. (訳注. 「ディスパッチャ」は「何か関数を呼び出すもの」くらいの意味です.) 例えば, 様々な異なった形式のデータを出力するプログラムを扱っている場合に, 各々の出力形式に対して個別の関数を定義し, 1つの呼び出し関数からデータ形式に合った関数を呼び出せます.
例えば, Web サイトの統計情報を HTML, XML, テキストの 3 つの形式で表示するプログラムを思い浮かべてみましょう. 出力形式の選択はコマンドラインや設定ファイルで指定できるとします. statsout モジュールには output_html, output_xml, output_text の 3 つの関数が定義されているとします. すると, 以下のように 1 つの出力関数でメインのプログラムが書けます.
import statsout def output(data, format="text"): output_function = getattr(statsout, "output_%s" % format) return output_function(data)
ところで, 前の例にバグがあるのが分かりましたか? かなりいい加減な文字列と関数の対応付けをしていて, エラーチェックは行っていません. statsout モジュールに関数が定義されていないフォーマットをユーザが指定した場合は何が起きるでしょうか? おそらく, getattr 関数は None を返し, それが正しい関数の代わりに output_function に割り当てられ, 関数を呼び出している次の行で呼び出しに失敗し例外を送出します. これは良くありません.
幸運なことに, getattr 関数は 3 つ目のオプションの引数にデフォルトの返り値を設定できます.
import statsout def output(data, format="text"): output_function = getattr(statsout, "output_%s" % format, statsout.output_text) return output_function(data)
ここで見たように, getattr 関数はかなり強力です. この関数は内省の真髄であり, さらに強力な例について後の章で見れます.
<< type, str, dir や他の組み込み関数を使う |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
リストのフィルター操作 >> |