web-dev-qa-db-fra.com

Python: vérifie si un objet est une séquence

En python, existe-t-il un moyen facile de savoir si quelque chose n'est pas une séquence? J'ai essayé de faire: if x is not sequence mais python n'a pas aimé ça

50
nicotine

iter(x) lèvera une TypeError si x ne peut pas être itéré - mais cette vérification "accepte" les ensembles et les dictionnaires, bien qu'elle "rejette" d'autres non-séquences telles que None et des nombres.

D'autre part, les chaînes (que la plupart des applications veulent considérer comme des "éléments individuels" plutôt que des séquences) sont en fait des séquences (donc, tout test, à moins que cela ne soit spécial pour les chaînes, va confirmer qu'ils le sont). Ainsi, ces simples contrôles ne suffisent souvent pas.

En Python 2.6 et supérieur, les classes de base abstraites ont été introduits et, parmi d’autres fonctionnalités puissantes, ils offrent un meilleur support systématique pour ce type de "contrôle de catégorie".

>>> 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

Vous remarquerez que les chaînes sont encore considérées comme "une séquence" (puisqu'elles sont ), mais au moins vous obtenez des dict et des sets à l'écart. Si vous souhaitez exclure les chaînes de votre concept "séquences", vous pouvez utiliser collections.MutableSequence (mais cela exclut également les n-uplets qui, comme les chaînes, sont des séquences, mais ne sont pas mutables), ou le font explicitement:

import collections

def issequenceforme(obj):
    if isinstance(obj, basestring):
        return False
    return isinstance(obj, collections.Sequence)

Assaisonner au goût et servir chaud! -)

64
Alex Martelli

Je pense que l'extrait de code ci-dessous fait ce que vous voulez:

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

La documentation Python 2.6.5 décrit les types de séquence suivants: chaîne, chaîne Unicode, liste, Tuple, tampon et xrange.

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

Pourquoi fais-tu ça? La manière habituelle ici est de demander un certain type de chose (une séquence ou un nombre ou un objet de type fichier, etc.), puis de l’utiliser sans rien vérifier. En Python, nous n'utilisons généralement pas de classes pour transporter des informations sémantiques, nous utilisons simplement les méthodes définies (cela s'appelle "typage de canard") Nous préférons également les API où nous savons exactement à quoi nous attendre. utilisez des arguments de mots clés, un prétraitement ou la définition d'une autre fonction si vous souhaitez modifier le fonctionnement d'une fonction.

0
Mike Graham

Pour Python 3 et 2.6+, vous pouvez vérifier s'il s'agit d'une sous-classe de collections.Sequence:

>>> import collections
>>> isinstance(myObject, collections.Sequence)
True

Dans Python 3.7, vous devez utiliser collections.abc.Sequence (collections.Sequence sera supprimé dans Python 3.8):

>>> import collections.abc
>>> isinstance(myObject, collections.abc.Sequence)
True

Toutefois, cela ne fonctionnera pas pour les séquences de type canard qui implémentent __len__() et __getitem__() mais ne font pas (comme elles devraient) la sous-classe collections.Sequence. Mais cela fonctionnera pour tous les types de séquence Python intégrés: listes, n-uplets, chaînes, etc.

Bien que toutes les séquences soient itérables, elles ne le sont pas toutes (par exemple, les ensembles et les dictionnaires sont itératifs, mais pas les séquences). La vérification de hasattr(type(obj), '__iter__') renverra True pour les dictionnaires et les ensembles.

0
Al Sweigart