Excepciones y control de flujo
Curso de Introducción al Pensamiento Computacional con Python
Contenido del curso
Hasta ahora hemos visto como las excepciones nos permiten controlar los posibles errores que pueden ocurrir en nuestro código. Sin embargo, dentro de la comunidad de Python tienen otro uso: control de flujo.
En este momento ya debes estar familiarizado con las estructuras de control flujo que ofrece Python (if... elif...else); entonces, ¿por qué es necesaria otra modalidad para controlar el flujo? Una razón muy específica: el principio EAFP (easier to ask for forgiveness than permission, es más fácil pedir perdón que permiso, por sus siglas en inglés).
El principio EAFP es un estilo de programación común en Python en el cual se asumen llaves, índices o atributos válidos y se captura la excepción si la suposición resulta ser falsa. Es importante resaltar que otros lenguajes de programación favorecen el principio LBYL (look before you leap, revisa antes de saltar) en el cual el código verifica de manera explícita las precondiciones antes de realizar llamadas.
Veamos ambos estilos:
# Python def busca_pais(paises, pais): """ Paises es un diccionario. Pais es la llave. Codigo con el principio EAFP. """ try: return paises[pais] except KeyError: return None
// Javascript /** * Paises es un objeto. Pais es la llave. * Codigo con el principio LBYL. */ function buscaPais(paises, pais) { if(!Object.keys(paises).includes(pais)) { return null; } return paises[pais]; }
Como puedes ver, el código de Python accede directamente a la llave y únicamente si dicho acceso falla, entonces se captura la excepción y se provee el código necesario. En el caso de JavaScript, se verifica primero que la llave exista en el objeto y únicamente con posterioridad se accede.
Es importante resaltar que ambos estilos pueden utilizarse en Python, pero el estilo EAFP es mucho más "pythonico".
Rafael Carpio
Siento que acá todos son expertos, yo tengo que leer las cosas unas 5 veces para entender un poco de lo que habla. Son palabras que literalmente se que dice, pero no hay una figura imaginativa en mi cerebro, esta totalmente en blanco.
Nicolás Ponce Vera
Así empieza la curva de aprendizaje para cualquier tema nuevo. Estoy en la misma situación pero por experiencias pasadas sé que se vuelve más sencillo con la práctica. Ánimo!
Ivan Ezequiel Mazzalay
Tranquilo Rafael, nos ha pasado a todos.. yo hace un par de años que empecé a meterme al tema del software por mi cuenta pero nunca pude dedicarme realmente como ahora y te puedo asegurar que he aprendido un montón, he tenido dudas y he tenido por ahí que recurrir a otras fuentes o al lápiz y al papel mas de una vez.. ánimos, a no bajar los brazos que con tiempo, estudio y práctica todo se aprende. Qué es lo que no entiendes? Comentame así te ayudo a entenderlo.
Gustavo Ulises Lira Reyes
Intente hacer un poco más dinámica esta parte e implementar lo que ha habiamos visto de diccionarios espero les sirva, aún me faltan implementar algunas cosas.
anime = { 'Shounen': 'Naruto', 'Mecha': 'Zoids', 'Vampiros': 'Hellsing', 'Espacio': 'Terra formars', 'Demonios': 'Kimetsu no Yaiba', 'Deportes': 'Capitan Tsubasa', 'Comedia': 'Ranma 1/2', 'Romance': 'Kimi no na wa', } def buscar_en_diccionario(diccionario,llave): try: return print(diccionario[llave]) except KeyError as e: print(e) return (f'{llave} no se encontro en el diccionario') def actualizar_genero_diccionario(diccionario,llave,valor): diccionario.update({llave:valor}) return print(f'El diccionario ha sido actualizado \nLos generos son: {diccionario.keys()}') def eliminar_valor_de_un_genero(diccionario,llave): try: diccionario_temp = {k:('Sin valor de llave' if diccionario.get(llave)==v else v) for k,v in diccionario.items()} diccionario.update(diccionario_temp) return print(f'Hola {diccionario.values()}') except NameError as e: print(e) return print(f'{llave} incorrecta') def manipular_dict(diccionario): print(f'Animes disponibles: {diccionario.values()}') print('Menu \n1. Buscar genero \n2. Actualizar Genero y anime \n3. Eliminar una anime') seleccion_menu = int(input('Seleccione un número del menu: ')) if seleccion_menu == 1: llave = str(input('Seleccione genero que desea buscar: ')) llamar_funcion = buscar_en_diccionario(diccionario,llave) return manipular_dict(diccionario) elif seleccion_menu ==2: llave = str(input('Seleccione genero que desea agregar: ')) valor = str(input('Seleccione anime que desea agregar al genero: ')) llamar_funcion = actualizar_genero_diccionario(diccionario,llave,valor) return manipular_dict(diccionario) elif seleccion_menu == 3: llave = str(input('Seleccione genero del anime que desea eliminar: ')) llamar_funcion = eliminar_valor_de_un_genero(diccionario,llave) return manipular_dict(diccionario) else: print('No se encontró número en el menu') return manipular_dict(diccionario) x = manipular_dict(anime)
Pablo Andres Onofre Riascos
Intentar hacer el mismo programa con switch(maneja menor las opciones) y te quedara perfecto, gracias compañero.
Andres Felipe Noguera Escandon
muy interesante.
Manuel Alejandro Hermoso
Digamos que en un buffet
El principio EAFP
El principio LBYL
Isay Humberto Lucas Hernandez
Creo que la analogía del buffet se aleja un poco del significado de EAFP y LBYL.
Estos estilos permiten "asumir" que un error podría ocurrir. En este caso, al buscar con una llave un valor en un diccionario/objeto.
Por ejemplo, asumiendo que el diccionario/objeto tiene 150 elementos (enumerados del 1 al 150) y por "accidente" se envía un 9999, la función está preparada para decir "Oye viejo, tu llave está muy bonita y todo pero no tengo un valor de país con dicha llave"; a simplemente dejar de funcionar.
**Es más fácil pedir perdón: **(Desarrollador porque agregaste esa excepción?! Pero bueno, nos salvó el día tu suposición)
A pedir permiso: (Oiga jefecito, me da chance de escribir este control de excepción? :( ).
Saludos!
Manuel Alejandro Hermoso
Interesante, me dejas pensando como lo podría aplicar a buffet :)
Braulio Alberto Bueno Pabon
EAFP:
try: x = my_dict["key"] except KeyError: # handle missing key
LBYL:
if "key" in my_dict: x = my_dict["key"] else: # handle missing key
La versión LBYL tiene que buscar la clave dentro del diccionario dos veces y también podría considerarse un poco menos legible.
Lorenzo Enrique Piñango Cerezo
Gracias :)
Wilson Delgado
Para complementar https://www.youtube.com/watch?v=ph1DuXvTrIw
José Contreras
Gracias bro!
Marcos Monteverde
gracias
Carmen Sánchez Salgado
Pythonico!
Juan Manuel Roa Mejia
Hola Carmen, espero te encuentres muy bien.
Me parece curioso tu código ya que noté que usaste el estilo EAFP para la función busca_pais() y también usaste implícitamente el estilo LBYL para poder imprimir el retorno.
Gran ejemplo para entenderlo :D
ALDO MATUS MARTINEZ
Script completo EAFP en Python :snake: :smiley:
def busca_pais(paises, pais): """ Paises es un diccionario. País es la llave. Código con el principio EAFP. """ try: return paises[pais] except KeyError: return None def run(): paises = { 'Mexico':1, 'Argentina':2, 'Colombia':3 } pais = input('Ingrese su pais: ') print(busca_pais(paises, pais)) if __name__ == '__main__': run()
Mauricio Obe
le falto una coma al 3 me sirvio para practicar tu codigo, gracias!
ALDO MATUS MARTINEZ
Me alegra esa es la intención, poder ayudar :smiley:
Esteban Ramírez García
Como dice la info, el estilo EAFP es más pythonico, sin embargo, para efectos de ilustración creo que esto podría servir
EAFP
try: return paises[pais] except KeyError: return None
LBYL
if pais not in paises.keys(): return None return paises[pais]
En LBYL, en la función built-in de los diccionarios llamada "keys" se obtiene un iterador, donde se evalúa si existe o no el key, cabe destacar, que en esta implementación me basé en el código escrito en JavaScript.
Esteban Ramírez García
Cuando digo "donde se valúa si existe o no el key", me refiero a esta implementación del método en el if que se puede observar, no me refiero a que la función realiza la evaluación.
Juan David Cepeda López
Python es muy elegante, se tenia que decir y se dijo.
Daniel Libardo Diaz Gonzalez
De acuerdo!
Carlos Iván Cortés Cruz
Ohh siii
Arturo Baduna
EAFP es in ingles(es mas fácil pedir perdón que pedir permiso) es mas pythonico LBYL revisa antes de salta jastripeico python es un adolescente audaz mientras a java es un viejo precavido
Edgar Norbey Usnas Jambuel
Me quedo mas claro con este comentario :)
Daniel Alejandro Cumaco Robayo
Java es horrible, mas feo que C jajaja
Nicolás Cabrera
Me parece mucho mas fácil el estilo EAFP, punto para Python 😂😂
Alejandro Barrios
realmente en Javascript el codigo no esta mal, pero parece hecho por alguien no especializado en javascript. la representacion real seria algo asi:
function buscaPais(paises, pais) { return paises[pais] }
si el pais existe, lo retorna, de lo contrario devuelve null.
Alejo Lemos
es verdad Alejandro me parecio muy raro ese codigo en js jajajaja
Jose Ramon Moreno Sanchez
pythonico :)
DAVID LEONARDO ALFONSO BENAVIDES
jajajaja es más fácil pedir perdón que permiso
Elmer Padilla Espinoza
Me gusto el uso de la palabra "pythonico"
David Jonatan Mora Bejarano
yo soy programador de C# se me hace más natural el estilo de LBYL
Carli Code
ProfesorGrace Hopper _ «Si es una buena idea, continuad y llevadla a término. Es mucho más fácil pedir disculpas que conseguir el permiso necesario»_
Diego Astudillo
pregunta para puntos
Leandro Tenjo
Realmente quiere preguntar algo?
O solo intenta subir el platzi rank?
. De ser así, es mucho fácil otras cosas como
… En cada una de las clases vi la misma “pregunta”, (comentario diría yo) Hay muchas formas. Pero el spam solo te da mala imagen.
Abril Rios
Realmente si queres subir puntos hacelo sin trampa además el único perjudicado a la larga serás vos. 😐
Luis Fernando Pedroza Taborda
La verdad no conocia sobre este estilo de programacion, Python esta lleno de sorpresas.
Gerson Montenegro
Quise emular la implementacion en JS del estilo LBYL usando la librería pydash (se instala con un pip install pydash desde la consola), y el código terminó así:
# LBYL style import pydash def buscaPais(paises, pais): result = pydash.objects.find_key(paises, lambda p: p == pais) return result print(f'LBYL style: {buscaPais(paises, "NombrePais")}')
Brandy Luis Lopez Pacheco
Excelente!
Clayton Jhordan Iliquin Zavaleta
Por favor si alguien me lo podría explicar de una mejor manera, leí los comentarios en los que trataban de explicarlo pero aún no me queda claro. Lo que entendí es algo así maso menos: ++ - EAFP( pedir permiso antes que disculpas) ++ Analiza todas las opciones y luego si no la encuentra manda una clave de error, si no hay error arroja la respuesta.
++ - LBYL(revisa antes de saltar) ++ En primer lugar verifica si encuentra el valor pedido en la busqueda, ahí salta el error, pero si verifica que esta el valor buscado ahí pasa a la otra condicional y arroja el resultado.
Marisol Catari Choquehuanca
Clayton: Mi explicación en palabras simples, veamos si te resulta más sencillo.
En ambos casos, no hay obligatoriedad de usarlos, solamente son 'estilos' saludables para manejar excepciones.
Ignacio Crespo
Gracias @marisolcatari por la explicación! Yo también tenía la misma duda :D