Pourquoi la liste n'a-t-elle pas une méthode "get" sûre comme un dictionnaire?
>>> d = {'a':'b'}
>>> d['a']
'b'
>>> d['c']
KeyError: 'c'
>>> d.get('c', 'fail')
'fail'
>>> l = [1]
>>> l[10]
IndexError: list index out of range
En fin de compte, il n’a probablement pas de méthode sécurisée .get
car un dict
est une collection associative (les valeurs sont associées à des noms) où il est inefficace de vérifier si une clé est présente (et de renvoyer sa valeur) sans lever d'exception, alors qu'il est super simple d'éviter que des exceptions accèdent à des éléments de la liste (comme la méthode len
est très rapide). La méthode .get
vous permet d'interroger la valeur associée à un nom et non d'accéder directement au 37ème élément du dictionnaire (ce qui ressemblerait davantage à ce que vous demandez de votre liste).
Bien sûr, vous pouvez facilement l'implémenter vous-même:
def safe_list_get (l, idx, default):
try:
return l[idx]
except IndexError:
return default
Vous pouvez même le synchroniser avec le constructeur __builtins__.list
dans __main__
, mais ce serait un changement moins important car la plupart du code ne l'utilise pas. Si vous voulez simplement utiliser ceci avec des listes créées par votre propre code, vous pouvez simplement sous-classer list
et ajouter la méthode get
.
Cela fonctionne si vous voulez le premier élément, comme my_list.get(0)
>>> my_list = [1,2,3]
>>> next(iter(my_list), 'fail')
1
>>> my_list = []
>>> next(iter(my_list), 'fail')
'fail'
Je sais que ce n'est pas exactement ce que vous avez demandé, mais que cela pourrait aider les autres.
Au lieu d'utiliser .get, utiliser comme ceci devrait être correct pour les listes. Juste une différence d'utilisation.
>>> l = [1]
>>> l[10] if 10 < len(l) else 'fail'
'fail'
Probablement parce que cela n'avait pas beaucoup de sens pour la sémantique de liste. Cependant, vous pouvez facilement créer le vôtre en sous-classant.
class safelist(list):
def get(self, index, default=None):
try:
return self.__getitem__(index)
except IndexError:
return default
def _test():
l = safelist(range(10))
print l.get(20, "oops")
if __== "__main__":
_test()
Essaye ça:
>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), 'fail')
4
>>> next(iter(a[i + 1:]), 'fail')
'fail'
La meilleure chose à faire est de convertir la liste en dict, puis d’y accéder avec la méthode get:
>>> my_list = ['a', 'b', 'c', 'd', 'e']
>>> my_dict = dict(enumerate(my_list))
>>> print my_dict
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e'}
>>> my_dict.get(2)
'c'
>>> my_dict.get(10, 'N/A')
Crédits à jose.angel.jimenez
Pour les fans "oneliner"…
Si vous voulez le premier élément d'une liste ou si vous voulez une valeur par défaut si la liste est vide, essayez:
liste = ['a', 'b', 'c']
value = (liste[0:1] or ('default',))[0]
print(value)
retourne a
et
liste = []
value = (liste[0:1] or ('default',))[0]
print(value)
retourne default
Exemples pour d'autres éléments…
liste = ['a', 'b', 'c']
print(liste[0:1]) # returns ['a']
print(liste[1:2]) # returns ['b']
print(liste[2:3]) # returns ['c']
Avec repli par défaut…
liste = ['a', 'b', 'c']
print((liste[0:1] or ('default',))[0]) # returns a
print((liste[1:2] or ('default',))[0]) # returns b
print((liste[2:3] or ('default',))[0]) # returns c
Testé avec Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
J'ai donc fait quelques recherches supplémentaires à ce sujet et il s'avère qu'il n'y a rien de spécifique à cela. Je me suis excité quand j'ai trouvé list.index (valeur), il retourne l'index d'un élément spécifié, mais rien ne permet d'obtenir la valeur à un index spécifique. Donc, si vous ne voulez pas utiliser la solution safe_list_get qui, à mon avis, est plutôt bonne. Voici quelques exemples de déclarations permettant de faire le travail pour vous en fonction du scénario:
>>> x = [1, 2, 3]
>>> el = x[4] if len(x) == 4 else 'No'
>>> el
'No'
Vous pouvez également utiliser None au lieu de 'No', ce qui est plus logique.:
>>> x = [1, 2, 3]
>>> i = 2
>>> el_i = x[i] if len(x) == i+1 else None
Aussi, si vous voulez juste obtenir le premier ou le dernier élément de la liste, cela fonctionne
end_el = x[-1] if x else None
Vous pouvez également en faire des fonctions mais j'ai quand même aimé la solution d'exception IndexError. J'ai expérimenté une version chiffrée de la solution safe_list_get
et je l'ai simplifiée un peu (pas de défaut):
def list_get(l, i):
try:
return l[i]
except IndexError:
return None
Je n'ai pas évalué pour voir ce qui est le plus rapide.
Les dictionnaires sont pour les recherches. Il est logique de demander si une entrée existe ou non. Les listes sont généralement itérées. Il n'est pas courant de demander si L [10] existe mais plutôt si la longueur de L est 11.