En python, quelle est la meilleure façon de tester si une variable contient une liste ou un tuple? (c.-à-d. une collection)
Est-ce isinstance()
aussi mal que suggéré 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 est lorsque j'ai une arborescence imbriquée indéfiniment profonde / une structure de données de listes de listes de listes de chaînes, etc. que j'explore avec un algorithme récursif et dont j'ai besoin pour savoir quand j'ai touché les nœuds "feuilles".
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 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 explicitementstr
ouunicode
comme ceci:NB Ne confondez pas
types.StringType
pourtypes.StringTypes
. Ce dernier intègrestr
etunicode
objets.Le
types
module est considéré par beaucoup comme obsolète en faveur de la vérification directe 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 explicitementstr
etunicode
, comme ceci:Éditer:
Mieux vaut encore:
Fin de la modification
Après l'un ou l'autre de ces éléments, vous pouvez vous remettre à vous comporter comme si vous obteniez une séquence normale, laissant les non-séquences lever des exceptions appropriées.
Voyez ce qui est "mal" à propos de la vérification de type, ce n'est pas que vous souhaitiez peut-être vous comporter différemment pour un certain type d'objet, c'est que vous limitez artificiellement votre fonction de faire la bonne chose avec des types d'objet inattendus qui autrement feraient la bonne chose. Si vous avez une solution de secours finale qui n'est pas vérifiée 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 effectuer une refactorisation, mais cela ne signifie pas nécessairement que vous devriez l'éviter du getgo.
la source
str
type, vous devez simplement l'utiliser directement, au lieu d'utilisertypes.StringType
ce qui n'est qu'un alias. Mais je ne pense pas que cette réponse réponde à la question posée, car il s'agissait "d'une collection". À moins que vous n'utilisiez un python suffisamment nouveau pour avoir leabc
module qui n'est pas quelque chose que vous pouvez utiliserisinstance
pour vérifier, et même dans ce cas, je recommanderais d'éviter la vérification si possible.assert isinstance(u'abc', str) == False
. Je suis d'accord qu'il vaut mieux comparer directement le type, plutôt que d'utiliser letypes
module, maistypes.StringTypes
fait quelque chose quistr
ne le fait pas: il retourne True forstr
etunicode
objets. Je vais modifier ma réponse pour proposer une double vérification comme alternative.isinstance
mal?" Et j'ai donné un contre-exemple qui (1) est une utilisation non malveillanteisinstance
, car avoir un repli signifie qu'il ne casse pas le typage de canard, et (2) est une bonne solution pour une motivation très courante que les gens ont pour vouloir vérifier si quelque chose est unlist
outuple
(c'est-à-dire pour les lever des ambiguïtés des chaînes).class Foo(str): pass
ce que vous voulez?la source
type([]) is list
retoursTrue
type(x) in [list,tuple]
est plus court.Il n'y a rien de mal à l'utiliser
isinstance
tant qu'il n'est pas redondant. Si une variable ne doit être qu'une liste / tuple, documentez l'interface et utilisez-la comme telle. Sinon, un chèque est parfaitement raisonnable:Ce type de vérification a de bons cas d'utilisation, comme avec la méthode standard commence par / fin avec les méthodes (bien que pour être précis, elles 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 pour résoudre ce problème, comme mentionné dans l'article auquel vous liez).
Une vérification explicite est souvent meilleure que d'essayer d'utiliser l'objet comme conteneur et de gérer l'exception - ce qui peut provoquer toutes sortes de problèmes avec l'exécution partielle ou inutile du code.
la source
set
objet est également un itérable, ce qui signifie que même si vous pouvez sûrement en extraire des éléments, mais il ne garantit pas un certain ordre, ce qui est très dangereux pour certains algorithmes. Dans les cas où la commande des éléments est importante, un algorithme utilisant cet extrait pourrait potentiellement générer des résultats différents sur différentes exécutions!Documentez l'argument comme devant être une séquence et utilisez-le comme une séquence. Ne cochez pas le type.
la source
Que diriez-vous
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 le peuvent, mais pas les types de chaînes.
la source
__iter__
.__iter__
pour une raison quelconque ...Sur les
type(list) is list
retours Python 2.8,false
je suggère de comparer le type de cette manière horrible:
(enfin au moins sur mon système, en utilisant anaconda sur Mac OS X Yosemite)
la source
type(list) is list
retoursFalse
parcetype(list)
esttype
, nonlist
.type(list()) is list
ou avec toute autre instance d'une liste reviendraTrue
.Python utilise le "Duck typing", c'est-à-dire que 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 juste faire ceci: c'est-à-dire utiliser l'objet dans
for var:
ou à l'var[idx]
intérieur d'untry
bloc, et si vous obtenez une exception, ce n'était pas un canard ...la source
var
une itération de chaîne se produira avec des résultats probablement inattendus.la source
Si vous avez juste besoin de savoir si vous pouvez utiliser la
foo[123]
notation avec la variable, vous pouvez vérifier l'existence d'un__getitem__
attribut (qui est ce que python appelle lorsque vous accédez par index) avechasattr(foo, '__getitem__')
la source
Doit être un test plus complexe si vous voulez vraiment gérer à peu près n'importe quoi comme argument de fonction.
Bien que, généralement, il suffit de préciser qu'une fonction s'attend à être itérable et de ne vérifier que
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 fassiez un fractionnement, etc., donc vous ne voulez pas crier sur les chaînes et si quelqu'un vous envoie quelque chose de bizarre, laissez-le simplement une exception.
la source
Un autre moyen simple de savoir si une variable est une liste ou un tuple ou de vérifier généralement le type de variable serait:
la source
En principe, je suis d'accord avec Ignacio, ci-dessus, mais vous pouvez également utiliser type pour vérifier si quelque chose est un tuple ou une liste.
la source