J'ai un code qui ressemble à ceci:
thing_index = thing_list.index(thing)
otherfunction(thing_list, thing_index)
ok donc c'est simplifié mais vous avez l'idée. Maintenant, thing
pourrait ne pas être réellement dans la liste, auquel cas je veux passer -1 en tant que thing_index
. Dans d’autres langues, c’est ce à quoi vous vous attendriez à ce que index()
revienne s’il ne trouvait pas l’élément. En fait, il jette une ValueError
.
Je pourrais faire ça:
try:
thing_index = thing_list.index(thing)
except ValueError:
thing_index = -1
otherfunction(thing_list, thing_index)
Mais cela semble sale, et je ne sais pas si ValueError
pourrait être élevé pour une autre raison. Je suis venu avec la solution suivante basée sur les fonctions du générateur, mais cela semble un peu complexe:
thing_index = ( [(i for i in xrange(len(thing_list)) if thing_list[i]==thing)] or [-1] )[0]
Y at-il un moyen plus propre de réaliser la même chose? Supposons que la liste n'est pas triée.
Il n'y a rien de "sale" à propos de l'utilisation de la clause try-except. C'est la manière pythonique. ValueError
sera généré uniquement par la méthode .index
, car c'est le seul code que vous avez là!
Pour répondre au commentaire:
En Python, il est plus facile de demander pardon que d'obtenir une permission philosophie est bien établie et noindex
ne soulèvera ce type d'erreur pour aucun autre problème. Pas que je puisse penser à aucun.
thing_index = thing_list.index(elem) if elem in thing_list else -1
Une ligne. Simple. Aucune exception.
Le type dict
a la fonction get
, où, si la clé n'existe pas dans le dictionnaire, le deuxième argument de get
est la valeur qu'il doit renvoyer. De même, il existe setdefault
, qui renvoie la valeur dans dict
si la clé existe, sinon il définit la valeur en fonction de votre paramètre par défaut, puis renvoie votre paramètre par défaut.
Vous pouvez étendre le type list
pour avoir une méthode getindexdefault
.
class SuperDuperList(list):
def getindexdefault(self, elem, default):
try:
thing_index = self.index(elem)
return thing_index
except ValueError:
return default
Ce qui pourrait alors être utilisé comme:
mylist = SuperDuperList([0,1,2])
index = mylist.getindexdefault( 'asdf', -1 )
Il n'y a rien de mal avec votre code qui utilise ValueError
. Voici encore un one-line si vous souhaitez éviter les exceptions:
thing_index = next((i for i, x in enumerate(thing_list) if x == thing), -1)
Ce numéro est une question de philosophie linguistique. En Java, par exemple, il a toujours existé une tradition voulant que les exceptions ne soient réellement utilisées que dans des "circonstances exceptionnelles", c'est-à-dire lorsque des erreurs se sont produites, plutôt que pour flow control . Au début, c'était pour des raisons de performances car les exceptions Java étaient lentes mais c'est maintenant devenu le style accepté.
En revanche, Python a toujours utilisé des exceptions pour indiquer le déroulement normal du programme, comme en élevant une ValueError
comme nous en discutons ici. Cela n’a rien de "sale" dans le style Python et il y en a beaucoup plus d’où cela vient. Un exemple encore plus courant est StopIteration
exception qui est déclenché par la méthode next()
d’un itérateur pour signaler qu’il n’y a plus de valeur.
Et ça:
otherfunction(thing_collection, thing)
Plutôt que d'exposer quelque chose d'aussi dépendant de l'implémentation, comme un index de liste dans une interface de fonction, transmettez la collection et l'élément, et laissez l'autre fonction fonctionner avec les problèmes de "test d'appartenance". Si une autre fonction est écrite pour être collection-type-agnostic, alors elle commencerait probablement par:
if thing in thing_collection:
... proceed with operation on thing
ce qui fonctionnera si thing_collection est une liste, un tuplet, un ensemble ou un dict.
Ceci est peut-être plus clair que:
if thing_index != MAGIC_VALUE_INDICATING_NOT_A_MEMBER:
qui est le code que vous avez déjà dans une autre fonction.
Si vous le faites souvent, il est préférable de le cuire dans une fonction d'assistance:
def index_of(val, in_list):
try:
return in_list.index(val)
except ValueError:
return -1
J'ai le même problème avec la méthode ".index ()" sur les listes. Je n'ai aucun problème avec le fait qu'il jette une exception, mais je suis fortement en désaccord avec le fait que c'est une ValueError non descriptive. Je pourrais comprendre si cela aurait été un IndexError, cependant.
Je peux comprendre pourquoi renvoyer "-1" serait également un problème, car il s'agit d'un index valide en Python. Mais de manière réaliste, je jamais n’attends une méthode ".index ()" pour renvoyer un nombre négatif.
Voici un one-liner (ok, c'est une ligne plutôt longue ...), parcourt la liste une seule fois et renvoie "Aucun" si l'élément n'est pas trouvé. Il serait trivial de le réécrire pour qu'il retourne -1, si vous le souhaitez.
indexOf = lambda list, thing: \
reduce(lambda acc, (idx, elem): \
idx if (acc is None) and elem == thing else acc, list, None)
Comment utiliser:
>>> indexOf([1,2,3], 4)
>>>
>>> indexOf([1,2,3], 1)
0
>>>
Qu'en est-il comme ceci:
temp_inx = (L + [x]).index(x)
inx = temp_inx if temp_inx < len(L) else -1
Et ça ???? :
li = [1,2,3,4,5] # create list
li = dict(Zip(li,range(len(li)))) # convert List To Dict
print( li ) # {1: 0, 2: 1, 3: 2, 4:3 , 5: 4}
li.get(20) # None
li.get(1) # 0