python何かがシーケンスではないかどうかを確認する簡単な方法はありますか?私はただやろうとしました:if x is not sequence
しかしpythonは気に入らなかった
iter(x)
は、TypeError
を反復できない場合x
を発生させますが、セットや辞書を「受け入れ」ますが、次のような他の非シーケンスを「拒否」します。 None
と数字。
一方、文字列(ほとんどのアプリケーションはシーケンスではなく「単一の項目」を検討したい)are実際のシーケンス(したがって、文字列に特別な場合を除いて、テストは文字列であることを確認します)。そのため、このような単純なチェックでは不十分なことがよくあります。
Python 2.6以降、abstract base classesが導入されました。他の強力な機能の中でも、このような「カテゴリチェック」に対するより優れた体系的なサポートを提供します。
>>> import collections
>>> isinstance([], collections.Sequence)
True
>>> isinstance((), collections.Sequence)
True
>>> isinstance(23, collections.Sequence)
False
>>> isinstance('foo', collections.Sequence)
True
>>> isinstance({}, collections.Sequence)
False
>>> isinstance(set(), collections.Sequence)
False
文字列はstillは「シーケンス」と見なされます(areであるため)が、少なくともディクテーションとセットは邪魔にならないことに注意してください。 「シーケンス」という概念から文字列を除外したい場合は、collections.MutableSequence
(ただし、文字列のようにシーケンスであるが、可変ではないタプルも除外します)、または明示的に行います:
import collections
def issequenceforme(obj):
if isinstance(obj, basestring):
return False
return isinstance(obj, collections.Sequence)
味付けし、ホットに味付けする!-)
以下のコードスニペットはあなたが望むことをすると思います:
def is_sequence(obj):
return hasattr(type(obj), '__iter__')
Python "adheres" duckタイピングなので、アプローチの1つはオブジェクトにメンバー(メソッド)があるかどうかをチェックすることです。
シーケンスには長さがあり、アイテムのシーケンスがあり、[ doc ]のスライスをサポートしています。したがって、次のようになります。
_def is_sequence(obj):
t = type(obj)
return hasattr(t, '__len__') and hasattr(t, '__getitem__')
# additionally: and hasattr(t, '__setitem__') and hasattr(t, '__delitem__')
_
これらはすべて特別なメソッドであり、__len__()
はアイテムの数を返し、__getitem__(i)
はアイテムを返します(順番にi)-th item、butマッピングなし)、__getitem__(slice(start, stop, step))
はサブシーケンスを返し、___setitem__
_および___delitem__
_のようにあなたは期待しています。これはそのような契約ですが、オブジェクトが実際にこれらを行うかどうかは、オブジェクトが契約を遵守しているかどうかによって決まります。
注、上記の関数はマッピングのためにTrue
も返します。 dict
。マッピングにもこれらのメソッドがあるため。これを克服するには、より重い作業を行うことができます:
_def is_sequence(obj):
try:
len(obj)
obj[0:0]
return True
except TypeError:
return False
_
Butほとんどの場合、これは必要ありません。オブジェクトがシーケンスであるかのように必要な処理を行い、必要に応じて例外をキャッチします。これはもっとPythonicです。
Python 2.6.5ドキュメント では、文字列、Unicode文字列、リスト、タプル、バッファ、xrangeのシーケンスタイプについて説明しています。
def isSequence(obj):
return type(obj) in [str, unicode, list, Tuple, buffer, xrange]
Python 3および2.6+の場合、それが_collections.Sequence
_のサブクラスであるかどうかを確認できます。
_>>> import collections
>>> isinstance(myObject, collections.Sequence)
True
_
Python 3.7では_collections.abc.Sequence
_を使用する必要があります(_collections.Sequence
_はPython 3.8)で削除されます:
_>>> import collections.abc
>>> isinstance(myObject, collections.abc.Sequence)
True
_
ただし、これは__len__()
および__getitem__()
を実装するが、サブクラス_collections.Sequence
_を(そうするべきではない)実装するアヒル型のシーケンスでは機能しません。ただし、すべての組み込みのPythonシーケンスタイプ:リスト、タプル、文字列などで機能します。
すべてのシーケンスは反復可能ですが、すべての反復可能がシーケンスではありません(たとえば、セットと辞書は反復可能ですが、シーケンスではありません)。 hasattr(type(obj), '__iter__')
をチェックすると、辞書とセットに対してTrue
が返されます。
なぜあなたはこれをやっている?ここでの通常の方法は、特定の種類(シーケンス、数字、またはファイルのようなオブジェクトなど)を要求し、何もチェックせずに使用することです。 Pythonでは、通常、クラスを使用してセマンティック情報を伝達するのではなく、単に定義されたメソッドを使用します(これは「ダックタイピング」と呼ばれます)。また、何を期待するかを正確に知っているAPIも好みます。関数の動作を変更する場合は、キーワード引数、前処理、または別の関数の定義を使用します。