If you want to prevent the program from ending with an exception because of trying to index with an index out of range none of the options that you sample will work, at the moment you try to evaluate a[2]
you will have the IndexError
.
With a conditional that checks the length of the list and checks whether the index is valid, something like this should be done:
a = [1, 2]
indice = 2
if not -len(a) <= indice < len(a):
print('Fuera de Rango')
else:
print(a[indice])
However you can use a block try-except
to capture the exception and handle it as you see fit:
a = [1, 2]
indice = 2
try:
print(a[indice])
except IndexError:
print("Fuera de rango")
Basically the interpreter tries to carry out what is inside the try
, in case of failure due to a IndexError
carries out what is inside the except
. You can capture any exception if except
is not followed by any error explicitly, although as you can imagine it can be a great cause of errors that are silenced:
try:
print(lista[indice])
except:
print("Algún error ocurrió")
You can handle different errors differently using several except
statements:
try:
print(lista[indice])
except IndexError:
print("Índice fuera de rango")
except TypeError:
print("Los indices de una lista han de ser enteros")
Or capture several types in the same block using a tuple:
try:
print(lista[indice])
except (IndexError, TypeError):
print("Índice no válido")
You can use a function that returns the item from the list if it exists, or a value that you want otherwise, without throwing an exception using the same idea (something similar to what the dict.get
method does for example) ).
a = [1, 2]
def get_list_element(lista, indice, default=None):
try:
return lista[indice]
except IndexError:
return default
elemento = get_list_element(a, 2)
print(elemento) # None
elemento = get_list_element(a, 1)
print(elemento) # 2
elemento = get_list_element(a, 2, default=0)
print(elemento) # 0
There are more more "elaborate" options creating our own container or inheriting class (not recommended for reasons that are not relevant) / composing from list
. However, if a container is required that implements the functionality of list
but customized a good option is to inherit collections.UserList
:
import collections
class MyList(collections.UserList):
def __getitem__(self, item, *args):
try:
return self.data.__getitem__(item)
except IndexError:
return None
a = MyList((1, 2))
print(a[1]) # 2
print(a[2]) # None
a.append(4)
print(a[2]) # 4
The class MyList
implements all the functions of a list but if we index with an incorrect index returns None
, it does not throw an exception.