322 votes

Tester si une variable est une liste ou un tuple

En python, quelle est la meilleure façon de tester si une variable contient une liste ou un tuple ? (c'est-à-dire une collection)

L'isinstance est-elle aussi mauvaise que suggérée ici ? http://www.canonical.org/~kragen/isinstance/

Mise à jour : la raison la plus courante pour laquelle je veux distinguer une liste d'une chaîne de caractères est lorsque j'ai un arbre imbriqué indéfiniment profond / une structure de données de listes de listes de listes de chaînes de caractères etc. que j'explore avec un algorithme récursif et j'ai besoin de savoir quand j'ai atteint les noeuds "feuilles".

77 votes

Il est un peu facile de rejeter le contrôle de type comme un mal. C'est une partie du langage. Si c'est si mauvais, quelqu'un devrait écrire un PEP pour le supprimer.

0 votes

Quel comportement voulez-vous avoir si vous obtenez un autre type de collection itérable (comme un ensemble ou une chaîne, par exemple) ?

4 votes

@Adam Crossland : "Ça fait partie de la langue." Tout comme la division par zéro. C'est évitable. Dans ce cas, sans information supplémentaire, c'est probablement complètement inutile. La plupart des vérifications de type en Python sont inutiles. Puisque pas tous est inutile, une vérification du type doit être présente. Mais cela ne signifie pas que c'est utile, précieux ou même une bonne idée.

665voto

wall-e Points 1727
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 votes

Cela ne semble pas fonctionner : type([]) ==> liste ; type([]) est liste ===> Faux

3 votes

Dans Python 2.7.5 : type([]) is list renvoie à True

75 votes

type(x) in [list,tuple] est plus courte.

126voto

jcdyer Points 7956

Allez-y et utilisez isinstance si vous en avez besoin. C'est un peu diabolique, car cela exclut les séquences personnalisées, les itérateurs et d'autres choses dont vous pourriez avoir besoin. Cependant, il faut parfois se comporter différemment si quelqu'un, par exemple, passe une chaîne de caractères. Dans ce cas, ma préférence irait à la vérification explicite de la présence de str ou unicode comme ça :

import types
isinstance(var, types.StringTypes)

N.B. Ne faites pas d'erreur types.StringType pour types.StringTypes . Ce dernier incorpore str et unicode objets.

Le site types est considéré par beaucoup comme obsolète en faveur de la vérification directe du type de l'objet. Si vous préférez ne pas utiliser le module ci-dessus, vous pouvez vérifier explicitement le type de l'objet. str et unicode comme ceci :

isinstance(var, (str, unicode)):

Edit :

C'est encore mieux :

isinstance(var, basestring)

Montage final

Après l'un ou l'autre de ces cas, vous pouvez revenir à un comportement comme si vous obteniez une séquence normale, en laissant les non séquences soulever les exceptions appropriées.

Vous voyez que ce qui est "mauvais" dans la vérification du type n'est pas que vous souhaitiez vous comporter différemment pour un certain type d'objet, c'est que vous empêchez artificiellement votre fonction de faire la bonne chose avec des types d'objets inattendus qui, autrement, feraient la bonne chose. Si vous avez un fallback final qui n'est pas vérifié par type, vous supprimez cette restriction. Il convient de noter que trop de vérification de type est une odeur de code qui indique que vous pourriez vouloir faire un peu de refactoring, mais cela ne signifie pas nécessairement que vous devez l'éviter dès le départ.

2 votes

Le module des types est un peu un artefact historique. Comme mentionné sur docs.python.org/dev/library/types.html#module-types si vous devez vraiment vérifier le str vous devez l'utiliser directement, au lieu d'utiliser le type types.StringType qui n'en est qu'un alias. Mais je ne pense pas que cette réponse réponde à la question telle qu'elle a été posée, car elle concernait "une collection". A moins que vous n'utilisiez un python assez récent pour avoir la fonction abc module qui n'est pas quelque chose que vous pouvez utiliser isinstance à vérifier, et même dans ce cas, je recommanderais d'éviter la vérification si possible.

1 votes

assert isinstance(u'abc', str) == False . Je suis d'accord sur le fait qu'il est préférable de vérifier le type directement, plutôt que d'utiliser la fonction types mais types.StringTypes fait quelque chose qui str ne le fait pas : il renvoie True pour str et unicode des objets. Je vais modifier ma réponse pour proposer une double vérification comme alternative.

1 votes

Je me rends compte que je n'ai pas répondu directement à la question de la vérification des recouvrements, mais la question réelle posée était "Est-ce que isinstance le mal ?" Et j'ai donné un contre-exemple qui (1) est une utilisation non-maléfique de la technologie de l'information. isinstance parce que le fait d'avoir une solution de repli signifie que cela ne casse pas le ducktyping, et (2) est une bonne solution pour une motivation très commune des gens qui veulent vérifier si quelque chose est un list ou tuple (c'est-à-dire pour les désambiguïser des chaînes de caractères).

43voto

Scott Griffiths Points 8867

Il n'y a rien de mal à utiliser isinstance tant que ce n'est pas redondant. Si une variable ne doit être qu'une liste/tuple, documentez l'interface et utilisez-la simplement comme telle. Sinon, une vérification est parfaitement raisonnable :

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

Ce type de vérification a quelques bons cas d'utilisation, comme avec la chaîne standard commence par / se termine par (bien que, pour être précis, ces méthodes soient implémentées en C dans CPython en utilisant une vérification explicite pour voir s'il s'agit d'un tuple - il y a plus d'une façon de résoudre ce problème, comme mentionné dans l'article dont vous donnez le lien).

Une vérification explicite est souvent meilleure que d'essayer d'utiliser l'objet comme un conteneur et de gérer l'exception - cela peut causer toutes sortes de problèmes avec du code exécuté partiellement ou inutilement.

23 votes

C'est un bon moyen de vérifier si une variable est itérable. Cependant, elle ne fonctionnera probablement pas pour les besoins de cette question. Sachez qu'une chaîne de caractères est également itérable et que cela créerait probablement un faux positif.

0 votes

A set est également un itérable, ce qui signifie que même si vous pouvez certainement extraire des éléments de cet objet, cela ne garantit pas un certain ordre, ce qui est très dangereux pour certains algorithmes. Dans les cas où l'ordre des éléments a de l'importance, un algorithme utilisant ce snippet pourrait potentiellement générer des résultats différents lors de différentes exécutions !

11voto

Documentez l'argument comme devant être une séquence, et utilisez-le comme une séquence. Ne vérifiez pas le type.

10voto

tetra5 Points 41
>>> l = []
>>> l.__class__.__name__ in ('list', 'tuple')
True

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X