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

179
demandé sur interstar 2010-02-02 18:00:23

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.

78
répondu jcdyer 2012-10-02 00:55:32
if type(x) is list:
    print 'a list'
elif type(x) is tuple:
    print 'a tuple'
else:
    print 'neither a tuple or a list'
415
répondu wall-e 2011-11-23 01:38:02

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.

36
répondu Scott Griffiths 2010-02-02 17:02:31

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

14
répondu Ignacio Vazquez-Abrams 2010-02-02 15:03:24

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.

10
répondu user1914881 2013-03-11 20:53:16

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

8
répondu Wim 2010-02-02 15:25:00

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)

8
répondu Xanderite 2014-11-05 15:46:13
>>> l = []
>>> l.__class__.__name__ in ('list', 'tuple')
True
6
répondu tetra5 2010-12-22 08:11:03

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__')

3
répondu Geoff Reedy 2010-02-02 17:15:38

, 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')
1
répondu Adam Crossland 2010-02-02 15:10:45

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.

1
répondu ZXX 2017-06-09 01:51:35