How to avoid an error

2

I have a list with 2 elements a=[1,2] if I put for example [2] as it will mark

> > Traceback (most recent call last):   File "<pyshell#13>", line 1, in <module>
>     if a[2]== IndexError(): IndexError: list index out of range

If I put a if to 'solve it' that says for example:

 if a[2]== IndexError: 
       print('Fuera de Rango')

Logical It will not work.

I know there are several ways to solve this problem, for example:

if a[2]==len(a):
    print('Fuera de Rango')

But the main question is whether you can avoid the error directly as in the first example without having to put a condition like length or something like that, but using a function that avoids these errors.

Thanks! and I hope you have made me understand.

    
asked by DDR 24.03.2018 в 19:57
source

2 answers

4

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.

    
answered by 24.03.2018 / 20:18
source
3

Errors that occur at runtime (that is, when a particular instruction is executing), trigger what is called an exception .

Exceptions can be captured from the code itself and made a decision on it with regard to what to do. Only when they are not captured do they end up coming into view of the user showing a Traceback like the one you have put in your question. In this Traceback it is informed which exception occurred, and in which line of code, as well as which functions were running at that moment (ie, from what function the one that caused the exception, and from which the previous one had been called, etc.)

In the documentation you have all the details on how to handle the exceptions , or how to launch your own .

A short summary would be the next one.

Handle exceptions

When you are going to execute a block of code that could fail with an exception, put that block of code inside a try: clause. After that clause put another call except X: , with X the name of an exception. Within this second block, you write code that will be executed in case the exception X occurs. The block except X you can repeat it several times with different cases of X , to handle each exception differently.

Like this:

try:
    dato = a[2]
except IndexError:
    print("Fuera de rango")
    dato = 0

Notice that when an exception occurs, in addition to (or instead of) printing what error has occurred, you must take some corrective action. In the previous example I assumed that we wanted to access a data, and that if we leave the data range, I do it equal to zero. This may make sense in your application or not have it. It depends on what you are going to do next with that data. Another option could be to make dato equal to None . Another option could be to abort the execution of the program with quit() to prevent it from executing anything else (which is what python does when it encounters an exception not handled by code).

Launch your own exception

You can also be writing a function that is going to be called from another site, and you want to detect possible errors and inform the caller that one of those errors has occurred. When you want to do that, you can put raise X() , with X the name of the exception you want to raise. It can be one of those that python has already defined, or others that you have created (they would be classes that directly or indirectly inherit from the class Exception ).

For example, your code could contain something like:

def obtener_elemento(a, n):
    if len(a) < n:
        raise IndexError("n debe ser menor que {}".format(len(a)))
    else:
        return a[n]

Whoever calls that function by passing an incorrect%% co_ would find the exception n that has been thrown from your code when entering the IndexError . If you have not handled that exception using if , the exception will go up to the next function that would have called the one that called yours. If at the end you reach the main program without anyone having dealt with the exception, the program will break and the user will be shown the message that we have set when the exception is thrown.

More details on the documentation mentioned above.

    
answered by 24.03.2018 в 20:26