変数がリストまたはタプルかどうかをテストする


234

Pythonでは、変数にリストまたはタプルが含まれているかどうかをテストする最良の方法は何ですか?(つまり、コレクション)

isinstance()ここで提案されているのと同じくらい悪ですか?http://www.canonical.org/~kragen/isinstance/

更新:リストを文字列から区別したい最も一般的な理由は、無限に深くネストされたツリー/文字列のリストのリストのリストなどのデータ構造があり、再帰的アルゴリズムで探索していて必要な場合です「リーフ」ノードをいつヒットしたかを知る。


72
型チェックを大雑把に却下するのは少し簡単です。言語の一部です。それがとても悪ければ、誰かがそれを削除するためにPEPを書くべきです。
Adam Crossland、2010

4
@Adam Crossland:「それは言語の一部です。」ちょうどゼロによる除算のように。それは避けられます。この場合、追加情報がなければ、おそらくまったく必要ありません。Pythonでのほとんどの型チェックは不要です。すべてが必要というわけではないので、いくつかの型チェックが存在する必要があります。しかし、だからと言って、それが役立つ、価値がある、または良いアイディアであるとは限りません。
S.Lott

11
つまり、何らかの型チェックが必要であると言っていますが、それでも、それは役に立たず、価値がなく、悪い考えです。すみません、それは意味がありません。
Glenn Maynard

18
「XXXは悪である」は、「XXXを実行するように要求している方法が、実際にいつ使用する必要があるかわからないこと、およびほぼ確実に別のものが必要であることを示唆している」の誤解を招く省略表現です。これが最も当てはまるケースです。
Glenn Maynard、

2
私はそれを悪として大まかに却下しませんでした。私はそれがいつ悪でいつ正当化できるかについて短いエッセイを書きました。そのエッセイは、正しい、間違っている、はっきりしている、あいまいで、楽しい、つまらないなど、多くのことかもしれませんが、1つではないことは、テクニックの広範な解任です。
Kragen Javier Sitaker、2010

回答:


101

isinstance必要に応じて使用してください。カスタムシーケンス、イテレータなど、実際に必要となる可能性があるものを除外しているため、多少悪です。ただし、たとえば、文字列を渡す人がいる場合は、別の動作が必要になることがあります。私の好みは明示的にチェックするstrunicode、そうすることです:

import types
isinstance(var, types.StringTypes)

NBドゥ間違えないtypes.StringTypeためにtypes.StringTypes。後者はstrおよびunicodeオブジェクトを組み込みます。

typesモジュールはあなたではなく、上記を使用していないと思いますので、もし、あなたが代わりに対して明示的に確認することができ、単にオブジェクトの型に対して直接確認するのに有利で時代遅れであることを多くの人に考えられているstrunicode、このように、:

isinstance(var, (str, unicode)):

編集:

まだ良いです:

isinstance(var, basestring)

編集を終了

これらのいずれかの後、通常のシーケンスを取得しているかのように動作にフォールバックし、非シーケンスが適切な例外を発生させるようにすることができます。

型チェックについて「悪い」ことは、特定の種類のオブジェクトに対して異なる動作をしたいということではありません。本来なら正しいことをするはずの予期しないオブジェクト型を使用して、関数が正しいことを行うことを人工的に制限するということです。タイプチェックされていない最終的なフォールバックがある場合は、この制限を削除します。型チェックが多すぎると、何らかのリファクタリングが必要になる可能性があることを示すコードの匂いになりますが、必ずしもgetgoからそれを回避する必要があるわけではありません。


2
タイプモジュールは、少し歴史的な成果物です。docs.python.org/dev/library/types.html#module-typesで述べたように、本当にstr型をチェックする必要がある場合は、types.StringType単なるエイリアスであるのではなく、直接使用する必要があります。しかし、これは「コレクション」に関するものだったので、この回答が質問どおりに回答するとは思わない。あなたがチェックabcするのに使用できるものではないモジュールを持つのに十分新しいPythonを使用しているのでない限りisinstance、そしてそれでも私は可能な限りチェックを避けることをお勧めします。
mzz

1
assert isinstance(u'abc', str) == False。私はむしろ使用するよりも、直接タイプに対してチェックすることをお勧めであることに同意typesモジュールを、しかしtypes.StringTypes、何かしstrないと。それがためにTrueを返しますstrunicodeオブジェクト。代わりにダブルチェックを提供するように私の応答を編集します。
jcdyer

1
コレクションを確認するという質問には直接答えなかったことがわかりましたが、実際に尋ねられた質問は「isinstance悪ですか?」でした。そして、私は反対の例を示しました。(1)isinstanceフォールバックがあることはダックタイピングを壊さないことを意味するので、(2)は、人々が持っているかどうかを確認したいという非常に一般的な動機に対する優れたソリューションです何かがlistorですtuple(つまり、文字列からそれらを明確にするため)。
jcdyer

私は同意しますが、カスタム型が文字列のように振る舞うこともしばしば有用であるという警告に同意します。しかし、PythonのOOはこれまでしか機能しません...
Kragen Javier Sitaker

あなたclass Foo(str): passは何をしたいですか?
jcdyer 2010

567
if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'

1
動作していないようです:type([])==>リスト; type([])is list ===> False
sten

3
Python 2.7.5の場合:type([]) is listリターンTrue
David Geiger

54
type(x) in [list,tuple]短いです。
Alex Holcombe 2015年

xとtype(x)がリストである場合:[]の不一致を回避するため
柴田健一

下にスクロールしなければなりませんでした。:D
Rithwik

38

isinstance冗長でない限り、使用に問題はありません。変数がリスト/タプルのみである必要がある場合は、インターフェースを文書化し、そのまま使用します。それ以外の場合、チェックは完全に合理的です。

if isinstance(a, collections.Iterable):
    # use as a container
else:
    # not a container!

このタイプのチェックには、標準文字列のstartswith / endswithメソッドなど、いくつかの良いユースケースがあります(正確には、これらはCPythonのCで実装されており、明示的なチェックを使用して、それがタプルかどうかを確認します-複数の方法がありますリンク先の記事で述べたように、この問題を解決するには)。

多くの場合、明示的なチェックは、オブジェクトをコンテナとして使用して例外を処理するよりも優れています。これにより、コードが部分的または不必要に実行されることであらゆる種類の問題が発生する可能性があります。


15
これは、変数が反復可能かどうかを確認するための良い方法です。ただし、この質問の目的ではおそらく機能しません。文字列も反復可能であり、おそらく誤検知を引き起こすことに注意してください。
Corey O.

setオブジェクトはまた、反復可能であるあなたは確かにそれから要素をポップすることができますが、一方で、それは、特定のアルゴリズムのための非常に危険なものである特定の順序を、保証するものではないことを意味します。要素の順序が重要な場合、このスニペットを使用するアルゴリズムは、実行ごとに異なる結果を生成する可能性があります。
koo 2014年


12

どうhasattr(a, "__iter__")ですか:?

返されたオブジェクトをジェネレータとして反復できるかどうかを通知します。デフォルトでは、タプルとリストはできますが、文字列型はできません。


これは本当に便利だと思いました。
javadba 2013年

8
文字列に対してもTrueになります(少なくともPython 3では)。
SzieberthAdam 2013

2
これは間違った答えです。タイプ 'str'にはメソッド ' iter 'もあるため。@SzieberthAdamは正しかった。タイプ「セット」も反復可能ですが、注文することはできません。
PADYMKO 2016年

また、辞書にはあります__iter__
2017

続行すると、何らかのカスタムタイプが__iter__何らかの理由で発生する可能性があります...
Alexander Irbis

10

Python 2.8のtype(list) is list戻り値false
では、この恐ろしい方法で型を比較す​​ることをお勧めします。

if type(a) == type([]) :
  print "variable a is a list"

(少なくとも私のシステムでは、Mac OS X Yosemiteでanacondaを使用しています)


1
type(a)is listもfalseと評価されますか?
Dmitriy Sintsov 2015


こんにちは、私は興味があります。なぜあなたの例は「恐ろしい」と思いますか?
セス・コネル

type(list) is list戻っFalseているためtype(list)であるtype、ではありませんlisttype(list()) is listまたは、リストの他のインスタンスではが返されTrueます。
Michael Greene

8

Pythonは「ダックタイピング」を使用します。つまり、変数がアヒルのようにクワックする場合、それはアヒルでなければなりません。あなたの場合、おそらくそれを反復可能にするか、特定のインデックスでアイテムにアクセスする必要があります。これを行う必要があります。つまり、ブロック内for var:またはブロックvar[idx]内のオブジェクトを使用します。try例外が発生した場合は、アヒルではありませんでした...


7
これの問題varは、文字列の反復が発生し、おそらく予期しない結果になる場合です。
ブライアンM.ハント

ブライアンM.ハントが述べた事実にもかかわらず、許可ではなく許しを求めるという点では、彼は非常にパイソン的な解決策です。
ゲーザTörök


3

foo[123]変数で表記を使用できるかどうかを知る必要があるだけの場合__getitem__は、次のコマンドで属性の存在(Pythonがインデックスでアクセスするときに呼び出すもの)の有無を確認できます。hasattr(foo, '__getitem__')


2

関数の引数としてほとんど何でも処理したい場合は、より複雑なテストを行う必要があります。

type(a) != type('') and hasattr(a, "__iter__")

ただし、通常は、関数が反復可能であることを期待していることをスペルアウトしてチェックするだけで十分type(a) != type('')です。

また、文字列の場合、単純な処理パスがあるか、うまくいき、分割するなどして、文字列に怒鳴りたくない場合や、誰かがあなたに変なものを送った場合は、彼に知らせてください例外。


2

変数がリストかタプルか、または一般的に変数の型をチェックするかを確認する別の簡単な方法は次のとおりです。

    def islist(obj):

        if ("list" in str(type(obj)) ): return True

        else : return False

1

原則として、上記のIgnacioに同意しますが、typeを使用して、タプルかリストかを確認することもできます。

>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.