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? (IE. une collection)
Isinstance est-il aussi diabolique que suggéré ici? http://www.canonical.org/~kragen/isinstance/
Update: la raison la plus courante pour laquelle je veux distinguer une liste d'une chaîne est quand j'ai une structure d'arbre / données imbriquée indéfiniment profonde de listes de listes de listes de chaînes, etc. que j'explore avec un algorithme récursif et j'ai besoin de savoir quand j'ai frappé le nœuds" feuille".
11 réponses
Allez-y et utilisez isinstance
Si vous en avez besoin. C'est un peu mal, car il exclut les séquences personnalisées, les itérateurs et d'autres choses dont vous pourriez avoir besoin. Cependant, vous devez parfois vous comporter différemment si quelqu'un, par exemple, passe une chaîne. Ma préférence serait de vérifier explicitement str
ou unicode
comme ceci:
import types
isinstance(var, types.StringTypes)
N.B. ne confondez pas types.StringType
avec types.StringTypes
. Ce dernier intègre des objets str
et unicode
.
Le module types
est considéré par beaucoup comme obsolète en faveur de simplement vérifier directement par rapport au type de l'objet, donc si vous préférez ne pas utiliser ce qui précède, vous pouvez également vérifier explicitement par rapport à str
et unicode
, comme ceci:
isinstance(var, (str, unicode)):
Modifier:
Mieux encore est:
isinstance(var, basestring)
Fin de l'édition
Après l'un ou l'autre de ceux-ci, vous pouvez vous comporter comme si vous obteniez une séquence normale, laissant les non-séquences lever les exceptions appropriées.
Voir la chose qui est" mal " à propos la vérification de type n'est pas que vous souhaitiez vous comporter différemment pour un certain type d'objet, c'est que vous limitez artificiellement votre fonction à faire la bonne chose avec des types d'objets inattendus qui feraient autrement la bonne chose. Si vous avez un repli final qui n'est pas coché 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 voudrez peut-être faire un refactoring, mais cela ne signifie pas nécessairement que vous devriez éviter à partir de la getgo.
if type(x) is list:
print 'a list'
elif type(x) is tuple:
print 'a tuple'
else:
print 'neither a tuple or a list'
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 en tant que telle. Sinon, un chèque est parfaitement raisonnable:
if isinstance(a, collections.Iterable):
# use as a container
else:
# not a container!
Ce type de vérification a de bons cas d'utilisation, comme avec la chaîne standard startswith / endswith méthodes (bien que pour être précis, celles-ci soient implémentées en C dans CPython en utilisant une vérification explicite pour voir si c'est un tuple-il y a plus de une façon de résoudre ce problème, comme mentionné dans l'article, vous lien).
Une vérification explicite vaut souvent mieux que d'essayer d'utiliser l'objet en tant que conteneur et de gérer l'exception - cela peut causer toutes sortes de problèmes avec l'exécution partielle ou inutile du code.
Documentez l'argument comme devant être une séquence, et utilisez-le comme une séquence. Ne vérifie pas le type.
Que diriez-vous de: hasattr(a, "__iter__")
?
Il indique si l'objet retourné peut être itéré en tant que générateur. Par défaut, les tuples et les listes peuvent, mais pas les types de chaînes.
Python utilise "Duck typing", c'est-à-dire si une variable kwaks comme un canard, ce doit être un canard. Dans votre cas, vous voulez probablement qu'il soit itérable, ou vous voulez accéder à l'élément à un certain index. Vous devriez simplement faire ceci: c'est à dire utiliser l'objet dans for var:
ou var[idx]
dans a try
bloc, et si vous obtenez une exception, elle n'était pas un canard...
Sur Python 2.8 type(list) is list
retourne false
Je suggère de comparer le type de cette manière horrible:
if type(a) == type([]) :
print "variable a is a list"
(bien au moins sur mon système, en utilisant anaconda sur Mac OS X Yosemite)
Si vous avez juste besoin de savoir si vous pouvez utiliser la notation foo[123]
avec la variable, vous pouvez vérifier l'existence d'un attribut __getitem__
(ce que Python appelle lorsque vous accédez par index) avec hasattr(foo, '__getitem__')
, En principe, je suis d'accord avec Ignacio, ci-dessus, mais vous pouvez également utiliser de type pour vérifier si quelque chose est un tuple ou une liste.
>>> a = (1,)
>>> type(a)
(type 'tuple')
>>> a = [1]
>>> type(a)
(type 'list')
Doit être un test plus complexe si vous voulez vraiment gérer n'importe quoi comme argument de fonction.
type(a) != type('') and hasattr(a, "__iter__")
Bien que, Généralement, il suffit de préciser qu'une fonction attend itérable et ensuite vérifier seulement type(a) != type('')
.
Il peut également arriver que pour une chaîne, vous ayez un chemin de traitement simple ou que vous soyez gentil et que vous fassiez un split, etc., donc vous ne voulez pas crier sur les chaînes et si quelqu'un vous envoie quelque chose de bizarre, laissez-le avoir une exception.