2008年10月16日木曜日

Pythonで変数の型をチェックする方法(Javaでいうinstanceofが使いたい)

  • リスト、辞書、タプルのようなイテレータが使える型には__iter__属性がある
  • ただし文字列には__iter__がない
  • Javaでいうinstanceofがやりたいときは、組み込み関数isinstance(obj, type)を使う
  • issubclass(obj, type)というのもある
基本的にPythonではあまり変数の型を気にしないようなのですが、
それでもどうしても型チェックがやりたくなるときはあります。
引数が本当にリストなのかどうかチェックしたりとか、引数をfor()文でループさせたいときとか。
そういった場合にPythonではどうすればいいのか調べてみました。
以下、すべてPython2.5.2で動作確認しています。

Javaでいうinstanceofに相当するPythonの組み込み関数はisinstance(obj, type)です。このメソッドを使えば、引数がリストか、文字列かといったチェックは簡単にできます。
#listかどうか
isinstance([1,2,3], list)

#辞書かどうか
isinstance({'a':1, 'b':2}, dict)

#タプルかどうか
isinstance((1,2,3), tuple)
引数がiterableかどうか(for文でループできるかどうか)の判定はちょっと複雑で、以下のようになります。
#itarableかどうか(Stringを含む)
#実際にはgetattr(obj, '__iter__', False)よりもhasattr(obj, '__iter__')のほうがスマート
isiterable = lambda obj: isinstance(obj, basestring) or getattr(obj, '__iter__', False)
isiterable('abcde')

#iterableかどうか(Stringは含まない)
getattr([1,2,3], '__iter__', False)
#またはhasattrを使って
hasattr([1,2,3], '__iter__')
普通のiterableなオブジェクトは__iter__属性を持っているのでこれですぐに判断できます。
しかしなぜか文字列だけは__iter__属性がないのでisinstance()を併用します。

※一部http://bytes.com/forum/thread514838.htmlより転載いたしました。ありがとうございました。