Pythonでは、変数にリストやタプルが含まれているかどうかをテストするための最良の方法は何ですか? (つまりコレクション)
ここで示唆されているように、意地悪は悪ですか? http://www.canonical.org/~kragen/isinstance/
更新:リストを文字列と区別したい最も一般的な理由は、再帰的アルゴリズムで探求している文字列のリストのリストのリストのような無限に深いネストされたツリー/データ構造があるときいつ「リーフ」ノードに到達したのかを知るために。
必要ならばisinstance
を使ってください。カスタムシーケンス、イテレータ、その他実際に必要となる可能性があるものは除外されているため、やや悪いことです。ただし、たとえば、誰かが文字列を渡すと、動作が異なることがあります。私の好みは、str
またはunicode
を明示的にチェックすることです。
import types
isinstance(var, types.StringTypes)
N.B. types.StringType
をtypes.StringTypes
と間違えないでください。後者はstr
とunicode
オブジェクトを組み込んでいます。
types
モジュールは、オブジェクトの型を直接チェックするだけのために時代遅れであると考えられているので、上記を使用したくない場合は、代わりにstr
とunicode
を明示的にチェックすることもできます。
isinstance(var, (str, unicode)):
編集:
もっと良いです:
isinstance(var, basestring)
編集終了
これらのどちらでも、通常のシーケンスを取得しているかのように振る舞い、シーケンスではないものに適切な例外を発生させることができます。
型チェックに関して「悪い」ことは、特定の種類のオブジェクトに対して異なる動作をしたくないということではありません。それ以外の場合は正しく行われない予期しないオブジェクト型を使用して関数を正しく行わないようにすることです。型チェックされていない最後のフォールバックがある場合は、この制限を取り除きます。注意しなければならないのは、型チェックが多すぎることは、何らかのリファクタリングをしたいと思うかもしれないことを示すコードの匂いですが、それは必ずしもgetgoからそれを避けるべきではないことを意味します。
if type(x) is list:
print 'a list'
Elif type(x) is Tuple:
print 'a Tuple'
else:
print 'neither a Tuple or a list'
冗長でない限り、isinstance
を使用しても問題ありません。もし変数がlist/Tupleだけであるべきなら、インターフェースを文書化してそれをそのまま使用してください。それ以外の場合、チェックは完全に合理的です。
if isinstance(a, collections.Iterable):
# use as a container
else:
# not a container!
この種のチェックは、標準の文字列 startswith / endswith メソッドのように、いくつかの良い使用例があります(正確に言うと、これらはCPythonのCに実装されています)それがタプルかどうかを確かめるための明示的なチェック - あなたがリンクしている記事で述べられているように、この問題を解決するには複数の方法があります。
明示的なチェックは、オブジェクトをコンテナとして使用して例外を処理するよりも優れています。コードが部分的にまたは不必要に実行されると、あらゆる種類の問題が発生する可能性があります。
引数をシーケンスにする必要があるとして文書化し、それをシーケンスとして使用します。種類を確認しないでください。
hasattr(a, "__iter__")
はどうですか?
返されたオブジェクトがジェネレータとして反復できるかどうかを示します。デフォルトでは、タプルとリストは可能ですが、文字列タイプは不可です。
Python 2.8ではtype(list) is list
はfalse
を返します
この恐ろしい方法で型を比較することをお勧めします。
if type(a) == type([]) :
print "variable a is a list"
(少なくとも私のシステムでは、Mac OS X Yosemiteでanacondaを使って)
Pythonは「ダックタイピング」を使用します。つまり、変数がアヒルのようにkwakする場合、アヒルでなければなりません。あなたの場合は、おそらくそれを反復可能にしたい、あるいは特定のインデックスでアイテムにアクセスしたいでしょう。つまり、try
ブロック内のfor var:
またはvar[idx]
内のオブジェクトを使用してください。例外が発生した場合、それはアヒルではありません...
>>> l = []
>>> l.__class__.__in ('list', 'Tuple')
True
変数でfoo[123]
表記法を使用できるかどうかを知る必要があるだけなら、hasattr(foo, '__getitem__')
を使って__getitem__
属性(インデックスでアクセスするときにpythonが呼び出すもの)の存在を確認できます。
原則として、私は上記のIgnacioに同意しますが、typeを使って何かがタプルかリストかをチェックすることもできます。
>>> a = (1,)
>>> type(a)
(type 'Tuple')
>>> a = [1]
>>> type(a)
(type 'list')
あなたが本当に関数の引数として何でも扱うことを本当に望むなら、もっと複雑なテストでなければなりません。
type(a) != type('') and hasattr(a, "__iter__")
ただし、通常は関数が反復可能であることを綴ってからtype(a) != type('')
だけをチェックするだけで十分です。
また、文字列については単純な処理パスを持っているか、ニースになって分割などを行うことになるかもしれません。例外。
変数がリストかタプルか、または一般に変数タイプをチェックするかどうかを調べるもう1つの簡単な方法は、次のとおりです。
def islist(obj):
if ("list" in str(type(obj)) ): return True
else : return False