Herramientas de usuario

Herramientas del sitio


informatica:programacion:python:cursos:introduccion_programacion_python:ejemplos_practicos

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
informatica:programacion:python:cursos:introduccion_programacion_python:ejemplos_practicos [2023/04/27 10:00] – [Testing: Pruebas unitarias] tempwininformatica:programacion:python:cursos:introduccion_programacion_python:ejemplos_practicos [2023/04/28 11:47] (actual) – [JSON en Python] tempwin
Línea 420: Línea 420:
 </code> </code>
  
-==== Testing: Pruebas unitarias =====+===== Testing: Pruebas unitarias =====
  
 Usaremos el módulo [[https://docs.python.org/3/library/unittest.html|unittest]] para las pruebas unitarias en Python. Usaremos el módulo [[https://docs.python.org/3/library/unittest.html|unittest]] para las pruebas unitarias en Python.
Línea 433: Línea 433:
  
 # Cálculo de las raíces # Cálculo de las raíces
-def segundo_grado(a, b, c):+def segundo_grado(a: float, b: float, c: float-> tuple: 
 + 
 +    """ 
 +    Calcula las soluciones reales de una ecuación de segundo grado. 
 +    Devuelve una tupla con las 2 soluciones reales o lanza una excepción  
 +    en caso de no tenerlas. 
 +    """
  
     d = b ** 2 - 4 * a *c     d = b ** 2 - 4 * a *c
Línea 491: Línea 497:
         self.assertAlmostEqual(segundo_grado(2, 4, -6), (1, -3))         self.assertAlmostEqual(segundo_grado(2, 4, -6), (1, -3))
  
 +    def test_ecuacion7(self):
 +        self.assertAlmostEqual(segundo_grado(1, -1, -1), (1.618033988749895, -0.6180339887498949))
 +
 +    def test_ecuacion8(self):
 +        
 if __name__ == '__main__': if __name__ == '__main__':
     unittest.main()             unittest.main()        
Línea 496: Línea 507:
  
 Si hacemos modificaciones en el código, los tests nos aseguran que todo siga funcionando correctamente o que el cambio que hemos hecho hace que no pasen los test. De esa manera, podremos detectar si algo hemos hecho mal. Si hacemos modificaciones en el código, los tests nos aseguran que todo siga funcionando correctamente o que el cambio que hemos hecho hace que no pasen los test. De esa manera, podremos detectar si algo hemos hecho mal.
 +
 +Además, al hacer tests, estamos dejando por escrito las pruebas que realizaremos en nuestro código.
 +
 +Para lanzar la batería de tests desde la línea de comandos:
 +
 +<code>
 +python -m unittest test_segundo_grado.py
 +</code>
 +
 +==== Conversión a números romanos ====
 +
 +Esta vez crearemos primero los tests y luego crearemos el código :
 +
 +<WRAP center round info 60%>
 +**TDD** (//Test Driven Development//): técnica de desarrollo en la que primero se define el test y luego el código que debe satisfacer el test.
 +</WRAP>
 +
 +
 +Fichero ''test_romanos.py'':
 +
 +<code python>
 +import unittest
 +
 +from romanos import roman
 +
 +class TestRomanos(unittest.TestCase):
 +
 +    def test_1(self):
 +        self.assertEqual(roman(1), "I")
 +        
 +    def test_2(self):
 +        self.assertEqual(roman(2), "II")
 +        
 +    def test_2(self):
 +        self.assertEqual(roman(2), "II")
 +        
 +    def test_3(self):
 +        self.assertEqual(roman(3), "III")
 +        
 +    def test_4(self):
 +        self.assertEqual(roman(4), "IV")
 +        
 +    def test_5(self):
 +        self.assertEqual(roman(5), "V")
 +
 +    def test_6(self):
 +        self.assertEqual(roman(6), "VI")
 +        
 +    def test_7(self):
 +        self.assertEqual(roman(7), "VII")
 +
 +    def test_9(self):
 +        self.assertEqual(roman(9), "IX")
 +        
 +    def test_10(self):
 +        self.assertEqual(roman(10), "X")
 +
 +    def test_13(self):
 +        self.assertEqual(roman(13), "XIII")
 +        
 +    def test_14(self):
 +        self.assertEqual(roman(14), "XIV")
 +        
 +    def test_17(self):
 +        self.assertEqual(roman(17), "XVII")
 +        
 +    def test_19(self):
 +        self.assertEqual(roman(19), "XIX")
 +        
 +    def test_20(self):
 +        self.assertEqual(roman(20), "XX")
 +        
 +    def test_27(self):
 +        self.assertEqual(roman(27), "XVII")
 +
 +    def test_33(self):
 +        self.assertEqual(roman(33), "XXXIII")
 +        
 +    def test_40(self):
 +        self.assertEqual(roman(40), "XL")
 +
 +    def test_49(self):
 +        self.assertEqual(roman(49), "XLIX")
 +
 +    def test_50(self):
 +        self.assertEqual(roman(50), "L")
 +
 +    def test_62(self):
 +        self.assertEqual(roman(62), "LXII")
 +        
 +    def test_90(self):
 +        self.assertEqual(roman(90), "XC")
 +        
 +    def test_97(self):
 +        self.assertEqual(roman(90), "XCVII")
 +        
 +    def test_100(self):
 +        self.assertEqual(roman(100), "C")
 +
 +    def test_333(self):
 +        self.assertEqual(roman(333), "CCCXXXIII")
 +        
 +    def test_400(self):
 +        self.assertEqual(roman(400), "CD")
 +        
 +    def test_500(self):
 +        self.assertEqual(roman(500), "D")
 +        
 +    def test_666(self):
 +        self.assertEqual(roman(666), "DCLXVI")
 +        
 +    def test_900(self):
 +        self.assertEqual(roman(900), "CM")
 +        
 +    def test_1000(self):
 +        self.assertEqual(roman(1000), "M")
 +        
 +    def test_1666(self):
 +        self.assertEqual(roman(1666), "MDCLXVI")
 +        
 +    def test_3999(self):
 +        self.assertEqual(roman(3999), "MMMCMXCIX")
 +
 +if __name__ == '__main__':
 +    unittest.main()
 +
 +</code>
 +
 +Creamos el programa ''romanos.py'':
 +
 +<code python>
 +"""
 +Romani ite domum!
 +
 +TDD - Test Driven Development
 +
 +1. Escribir un test (que inicialmente falle)
 +2. Escribir el código que haga pasar el test
 +3. Refactorizar el código: optimización, limpieza, etc
 +(Y vuelta a empezar...)
 +"""
 +
 +def roman(n: int) -> str:
 +
 +    cantidades = [
 +        (1000, "M"), (900, "CM"), (500, "D"), (400, "CD"), (100, "C"), 
 +        (90, "XC"), (50, "L"), (40, "XL"), (10, "X"), (9, "IX"), 
 +        (5, "V"), (4, "IV"), (1, "I")
 +    ]
 +
 +    conv = ""
 +    
 +    for cant, letras in cantidades:
 +        while n >= cant.
 +            n -= cant
 +            conv += letras
 +    
 +    return conv
 +</code>
 +
 +Opción con recursividad:
 +
 +<code python>
 +def roman2(n: int) -> str:
 +
 +    if n >= 1000:
 +        return "M" + roman2(n - 1000)
 +    elif n >= 900:
 +        return "CM" + roman2(n - 900)
 +    elif n >= 500:
 +        return "D" + roman2(n - 500)    
 +    elif n >= 400:
 +        return "CD" + roman2(n - 400)    
 +    elif n >= 100:
 +        return "C" + roman2(n - 100)            
 +    elif n >= 90:
 +        return "XC" + roman2(n - 90)            
 +    elif n >= 50:
 +        return "L" + roman2(n - 50)            
 +    elif n >= 40:
 +        return "XL" + roman2(n - 40)            
 +    elif n >= 10:
 +        return "XL" + roman2(n - 10)            
 +    elif n >= 9:
 +        return "XL" + roman2(n - 9)            
 +    elif n >= 5:
 +        return "V" + roman2(n - 5)            
 +    elif n >= 4:
 +        return "IV" + roman2(n - 4)            
 +    elif n >= 1:
 +        return "I" + roman2(n - 1)                    
 +    else:
 +        return ""
 +</code>
 +
 +  * [[https://codewars.com|codewars]]: retos de programación
 +
 +===== JSON =====
 +
 +JSON (//JavaScript Object Notation//) formato para el intercambio de información.
 +
 +JSON no son más que objetos (que son equivalentes a los diccionarios de Python) y listas.
 +
 +Se trata de texto.
 +
 +  * https://www.json.org/json-en.html
 +
 +==== JSON en Python ====
 +
 +Aspecto de un JSON, que lo representamos como string:
 +
 +<code python>
 +datos_json = '''
 +{
 +    "glossary": {
 +        "title": "example glossary",
 +        "GlossDiv": {
 +            "title": "S",
 +            "GlossList": {
 +                "GlossEntry": {
 +                    "ID": "SGML",
 +                    "SortAs": "SGML",
 +                    "GlossTerm": "Standard Generalized Markup Language",
 +                    "Acronym": "SGML",
 +                    "Abbrev": "ISO 8879:1986",
 +                    "GlossDef": {
 +                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
 +                        "GlossSeeAlso": [
 +                            "GML",
 +                            "XML"
 +                        ]
 +                    },
 +                    "GlossSee": "markup"
 +                }
 +            }
 +        }
 +    }
 +}
 +'''
 +</code>
 +
 +  * [[https://docs.python.org/3/library/json.html|Tratamiento de JSON en Python (documentación oficial)]]
 +
 +<code python>
 +# Biblioteca de Python para el tratamiento de JSON
 +import json
 +
 +# Cargamos a partir de un string un objeto JSON/diccionario
 +datos = json.loads(datos_json)
 +
 +type(datos) # dict
 +
 +datos.keys() # dict_keys(['glossary'])
 +
 +glossary = datos['glossary'] # dict
 +
 +glossary.keys() # dict_keys(['title', 'GlossDiv'])
 +
 +paises_capitales = {
 +    "España": "Madrid",
 +    "Portugal": "Lisboa",
 +    "Italia": "Roma",
 +    "Francia": "Paris",
 +    "Alemania": "Berlin"
 +}
 +
 +type(paises_capitales) # dict
 +
 +# Si queremos pasar de un diccionario a string en formato JSON
 +json.dumps(paises_capitales)
 +</code>
 +
 +  * [[https://jsonviewer.stack.hu/|Online JSON Viewer]]
 +
 +Si procesamos un JSON inválido:
 +
 +<code python>
 +mal_json = '''
 +{"mal": "json"
 +'''
 +
 +try:
 +    json.loads(mal_json)
 +except json.JSONDecodeError as error:
 +    print("Error cargando JSON")
 +</code>
 +
 +
 +disculpa, Jairo, sabes hasta qué día tenemos disponible el acceso al campus virtual?
informatica/programacion/python/cursos/introduccion_programacion_python/ejemplos_practicos.1682582439.txt.gz · Última modificación: por tempwin