web-dev-qa-db-ja.com

Python:オブジェクトがシーケンスかどうかを確認します

python何かがシーケンスではないかどうかを確認する簡単な方法はありますか?私はただやろうとしました:if x is not sequenceしかしpythonは気に入らなかった

58
nicotine

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)

味付けし、ホットに味付けする!-)

67
Alex Martelli

以下のコードスニペットはあなたが望むことをすると思います:

def is_sequence(obj):
    return hasattr(type(obj), '__iter__')
9
Humoyun Ahmad

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です。

6
fikr4n

Python 2.6.5ドキュメント では、文字列、Unicode文字列、リスト、タプル、バッ​​ファ、xrangeのシーケンスタイプについて説明しています。

def isSequence(obj):
    return type(obj) in [str, unicode, list, Tuple, buffer, xrange]
5

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が返されます。

1
Al Sweigart

なぜあなたはこれをやっている?ここでの通常の方法は、特定の種類(シーケンス、数字、またはファイルのようなオブジェクトなど)を要求し、何もチェックせずに使用することです。 Pythonでは、通常、クラスを使用してセマンティック情報を伝達するのではなく、単に定義されたメソッドを使用します(これは「ダックタイピング」と呼ばれます)。また、何を期待するかを正確に知っているAPIも好みます。関数の動作を変更する場合は、キーワード引数、前処理、または別の関数の定義を使用します。

0
Mike Graham