web-dev-qa-db-fra.com

Pourquoi la liste n'a-t-elle pas de méthode "get" sécurisée comme un dictionnaire?

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
220
CSZ

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.

94
Nick Bastin

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.

56
Jake

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'
39
YOU

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()
38
Keith

Essaye ça:

>>> i = 3
>>> a = [1, 2, 3, 4]
>>> next(iter(a[i:]), 'fail')
4
>>> next(iter(a[i + 1:]), 'fail')
'fail'
16
Vsevolod Kulaga

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')
13
fab

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)

10
qräbnö

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.

5
radtek

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.

4
Apprentice Queue