web-dev-qa-db-fra.com

Obtenir une valeur par défaut sur un index hors de portée dans Python

a=['123','2',4]
b=a[4] or 'sss'
print b

Je veux obtenir une valeur par défaut lorsque l'index de la liste est hors de portée (ici: 'sss').

Comment puis-je faire ceci?

69
zjm1126

Dans l'esprit Python de "demander pardon, pas de permission", voici une façon:

try:
    b = a[4]
except IndexError:
    b = 'sss'
86
Thomas

Dans l'esprit non-Python de "demander la permission, pas le pardon", voici une autre façon:

b = a[4] if len(a) > 4 else 'sss'
58
Thomas

Dans le Python esprit de beau est mieux que laid

Code méthode de golf, en utilisant la tranche et le déballage (je ne sais pas si c'était valable il y a 4 ans, mais c'est en python 2.7 + 3.3)

b,=a[4:5] or ['sss']

Plus agréable qu'une fonction d'emballage ou essayez d'attraper IMHO, mais intimidant pour les débutants. Personnellement, je trouve que le déballage de Tuple est bien plus sexy que la liste [#]

en utilisant le tranchage sans déballage:

b = a[4] if a[4:] else 'sss'

ou, si vous devez le faire souvent, et ne vous occupez pas de faire un dictionnaire

d = dict(enumerate(a))
b=d.get(4,'sss')
21
00500005

autrement:

b = (a[4:]+['sss'])[0]
15
maep

Vous pouvez créer votre propre classe de liste:

class MyList(list):
    def get(self, index, default=None):
        return self[index] if len(self) > index else default

Vous pouvez l'utiliser comme ceci:

>>> l = MyList(['a', 'b', 'c'])
>>> l.get(1)
'b'
>>> l.get(9, 'no')
'no'
13
gecco

Vous pouvez également définir une petite fonction d'aide pour ces cas:

def default(x, e, y):
    try:
        return x()
    except e:
        return y

Il renvoie la valeur de retour de la fonction x, sauf s'il a levé une exception de type e; dans ce cas, il renvoie la valeur y. Usage:

b = default(lambda: a[4], IndexError, 'sss')

Edit: Il a fait qu'il n'attrape qu'un seul type d'exception spécifié.

Les suggestions d'amélioration sont toujours les bienvenues!

5
Thomas

Pour un cas courant où vous voulez le premier élément, vous pouvez faire

next(iter([1, 2, 3]), None)

Je l'utilise pour "déballer" une liste, éventuellement après l'avoir filtrée.

next((x for x in [1, 3, 5] if x % 2 == 0), None)

ou

cur.execute("SELECT field FROM table")
next(cur.fetchone(), None)
5
Pepijn
try:
    b = a[4]
except IndexError:
    b = 'sss'

Une manière plus propre (ne fonctionne que si vous utilisez un dict):

b = a.get(4,"sss") # exact same thing as above

Voici une autre façon que vous aimeriez (encore une fois, seulement pour les dict):

b = a.setdefault(4,"sss") # if a[4] exists, returns that, otherwise sets a[4] to "sss" and returns "sss"
3
Vlad the Impala

Je suis tout pour demander la permission (c'est-à-dire que je n'aime pas la méthode tryexcept). Cependant, le code devient beaucoup plus propre lorsqu'il est encapsulé dans une méthode:

def get_at(array, index, default):
    if index < 0: index += len(array)
    if index < 0: raise IndexError('list index out of range')
    return array[index] if index < len(a) else default

b = get_at(a, 4, 'sss')
1
Konrad Rudolph

Comme il s'agit d'un succès de Google, il convient probablement également de mentionner que le package standard "collections" a un "defaultdict" qui fournit une solution plus flexible à ce problème.

Vous pouvez faire des choses intéressantes, par exemple:

twodee = collections.defaultdict(dict)
twodee["the horizontal"]["the vertical"] = "we control"

En savoir plus: http://docs.python.org/2/library/collections.html

1
Jonathan Mayer

Si vous cherchez un moyen maintenable d'obtenir des valeurs par défaut sur l'opérateur d'index, j'ai trouvé ce qui suit utile:

Si vous remplacez operator.getitem à partir du module opérateur pour ajouter un paramètre par défaut facultatif, vous obtenez un comportement identique à l'original tout en conservant la compatibilité descendante.

def getitem(iterable, index, default=None):
  import operator
  try:
    return operator.getitem(iterable, index)
  except IndexError:
    return default
1
Alex

Vous utilisez try/catch?

try:
    b=a[4]
except IndexError:
    b='sss'
0
zoli2k

Si vous recherchez un hack rapide pour réduire la longueur du code par caractère, vous pouvez essayer ceci.

a=['123','2',4]
a.append('sss') #Default value
n=5 #Index you want to access
max_index=len(a)-1
b=a[min(max_index, n)]
print(b)

Mais cette astuce n'est utile que lorsque vous ne souhaitez plus de modifications supplémentaires de la liste

0
Vikas Kumar