Módulos y depuración en Python: pruebas y aserciones

Aprende a aprovechar código existente y a hacer que tu propio código funcione de forma fiable. Importa módulos de la biblioteca estándar de Python, como math y random, escribe tus propios módulos e instala paquetes de PyPI con pip. Después, lee trazas de excepciones (tracebacks) y mensajes de error, detecta errores de programación (bugs) con un proceso de depuración paso a paso y comprueba tus funciones con sentencias assert y tus primeras pruebas unitarias.

PrincipianteUnidad 9 de 10 del curso Curso de Introducción a la programación con Python

Lo que aprenderás

  1. Incorpora código ya escrito a un programa con sentencias import, usa módulos de la biblioteca estándar como math y random, divide tu propio código en módulos e instala paquetes de terceros con pip.
    • Incorpora código a un programa con sentencias import
      Usa correctamente import, from … import y as, accede a nombres con la notación de punto y distingue los errores de importación.
    • Calcula y realiza simulaciones con math, random y otros módulos estándar
      Usa las funciones principales de math y random, evita sus errores habituales y conoce algunos otros módulos de uso frecuente de la biblioteca estándar.
    • Escribe e importa tus propios módulos
      Divide el código en tus propios archivos .py, impórtalos, evita conflictos de nombres y usa if __name__ == "__main__": para que un archivo pueda ejecutarse e importarse.
    • Instala y gestiona paquetes con pip
      Instala, inspecciona, actualiza y elimina paquetes de terceros de PyPI, impórtalos con el nombre correcto y resuelve los problemas habituales de instalación.
  2. Usa la salida de error de Python para averiguar dónde ha fallado un programa y por qué, y distingue entre errores de sintaxis, errores de ejecución y errores lógicos.
    • Lee una traza de excepción de abajo arriba
      Identifica el tipo de excepción, el mensaje, la línea que falla y la cadena de llamadas que ha llevado hasta ella.
    • Reconoce errores habituales y sus causas
      Relaciona los tipos de excepción más frecuentes con sus causas y soluciones habituales, y detecta errores lógicos que no generan mensajes.
  3. Localiza la causa de un error de programación con un proceso paso a paso, sin hacer cambios a ciegas, e inspecciona un programa en ejecución con llamadas a print y un depurador.
    • Sigue un proceso de depuración paso a paso
      Reproduce un error de programación, formula y comprueba una hipótesis, acota la causa, corrígela y vuelve a probar.
    • Inspecciona un programa con llamadas a print, tablas de seguimiento y un depurador
      Observa cómo cambian los valores durante la ejecución del código añadiendo llamadas a print, siguiendo la ejecución a mano o deteniéndola en puntos de interrupción.
  4. Usa assert para indicar qué debe ser verdadero, escribe pequeñas pruebas automatizadas para tus funciones y ejecútalas e interpreta sus resultados con el módulo estándar unittest.
    • Comprueba supuestos con sentencias assert
      Escribe sentencias assert con mensajes claros y reconoce cuándo las aserciones son la herramienta adecuada y cuándo no.
    • Escribe tus primeras pruebas unitarias para tus funciones
      Escribe funciones de prueba con aserciones, elige casos típicos, valores límite y casos límite, y utiliza las pruebas que fallan para detectar y corregir errores de programación.
    • Organiza y ejecuta pruebas con unittest
      Escribe pruebas con unittest.TestCase, ejecútalas e interpreta el informe de pruebas superadas, fallos y errores.

Guía de estudio de Módulos y depuración en Python

4 capítulos

1

Reutiliza módulos e instala paquetes

El código importado permite que un programa pequeño use cálculos, simulaciones y herramientas escritos en otros lugares. Elegirás una forma de importación, trabajarás con funciones de la biblioteca estándar y organizarás tus propias funciones para que otro archivo pueda reutilizarlas. La instalación añade otra pregunta: ¿qué Python recibe un paquete de terceros? Entender esa relación facilita diagnosticar la ausencia de un módulo y mantener claros los nombres de cada programa.

1.1 Importa un módulo o nombres seleccionados

Un módulo contiene código Python que otro programa puede reutilizar. La mayoría de los módulos son archivos .py. La biblioteca estándar viene con Python; el código de terceros requiere una instalación aparte. Un paquete agrupa módulos relacionados, normalmente en una carpeta.

Haz que la llamada coincida con la importación

Una importación crea nombres en tu programa. La forma que eliges determina cómo llamas al código importado.

SentenciaNombre creadoEjemplo de llamada
import mathmathmath.sqrt(16)
from math import sqrtsqrtsqrt(16)
import statistics as statsstatsstats.mean([2, 4, 9])
from random import randint as rollrollroll(1, 6)

La notación de punto consiste en buscar un nombre dentro de un módulo u objeto. En math.sqrt(16), Python encuentra sqrt dentro de math y la llama con 16. El resultado es 4.0. La constante math.pi no necesita paréntesis de llamada porque es un valor, no una función.

Después de import math, usar solo sqrt(16) lanza NameError: el programa tiene un nombre para el módulo, pero no un nombre independiente para sqrt. Después de usar únicamente from math import sqrt, el error inverso, math.sqrt(16), también lanza NameError porque math no se ha vinculado. Un alias sustituye el nombre habitual de la vinculación importada: import statistics as stats crea stats, no ambos nombres.

Resuelve el mismo cálculo de dos formas

Un triángulo rectángulo tiene catetos de 3 y 4. Primero eleva al cuadrado los catetos y suma los resultados; después calcula la raíz cuadrada.

import math

length = math.sqrt(3**2 + 4**2)
print(length)  # 5.0

La expresión dentro de la llamada se convierte en 9 + 16 y después en 25; sqrt devuelve 5.0. Con from math import sqrt, escribe en su lugar length = sqrt(3**2 + 4**2). Usar el prefijo del módulo permite ver de dónde procede una función y mantiene sus demás nombres fuera del espacio de nombres de tu programa. La propia vinculación math sí puede sustituir una variable anterior llamada math.

Mantén claros los nombres

Evita from math import *. Esta importación con comodín incorpora nombres públicos a tu programa sin nombrarlos individualmente. Por ejemplo, e = 5 seguido de esa importación cambia e a 2.718281828459045. Una importación que parece no tener relación puede, por tanto, cambiar un cálculo posterior. PEP 8 recomienda importaciones explícitas y las coloca al principio, con un módulo por línea: primero la biblioteca estándar, después los paquetes de terceros y, por último, tus propios módulos.

Python ejecuta el código de nivel superior de un módulo en su primera importación durante una ejecución del programa. Las importaciones posteriores reutilizan el módulo cargado; no vuelven a iniciarlo.

Usa el error para elegir la solución
ErrorQué revisar
ModuleNotFoundError con import mathhLa escritura del nombre del módulo y su instalación
ImportError con from math import square_rootEl nombre solicitado al módulo
AttributeError con math.sqroot(16)El nombre que sigue al punto

En la consola interactiva, ejecuta import math y después dir(math) para enumerar sus nombres. Ejecuta help(math.sqrt) para leer la documentación de una función. La referencia oficial de la biblioteca de Python explica sus argumentos y su resultado.

Puntos clave

  • import module crea una vinculación con un módulo; accede a su contenido con la notación de punto.
  • from module import name crea la vinculación seleccionada; as elige un alias.
  • Las importaciones explícitas mantienen claro el origen de los nombres y reducen las sustituciones accidentales.
  • Los errores de importación distinguen entre un módulo no encontrado, un nombre importado no disponible y un atributo ausente.
  • dir() enumera nombres; help() explica cómo usar uno.

1.2 Elige funciones de math y random

La biblioteca estándar proporciona herramientas probadas para cálculos y simulaciones. Para elegir una función, empieza por el resultado que necesitas: un recuento entero, una medida redondeada, un elemento aleatorio o una lista reordenada.

Redondear tiene varios significados

Después de import math, math.sqrt(16) devuelve el número de coma flotante 4.0. math.pi y math.e proporcionan las constantes 3.141592653589793 y 2.718281828459045. math.factorial(5) multiplica los enteros de 1 a 5 y devuelve 120.

ExpresiónResultadoSignificado
math.floor(7.9)7Mayor entero que no supera el valor
math.ceil(2.1)3Menor entero que no es inferior al valor
math.floor(-2.5)-3Hacia abajo significa hacia menos infinito
int(-3.5)-3La conversión trunca hacia cero
round(2.5)2Un valor exactamente a mitad de camino se redondea al par
round(3.5)4El entero par vecino es 4

Para una pared de 23 metros cuadrados y 10 metros cuadrados por lata de pintura, la división da 2.3 latas. Comprar latas enteras requiere math.ceil(23 / 10), que devuelve 3. round(2.3) da 2 y deja una cantidad de pintura insuficiente.

La función incorporada round() no necesita ninguna importación. Para un círculo de radio 2, round(math.pi * 2 ** 2, 2) da 12.57. El redondeo cambia la precisión de un número; es una tarea distinta de comprar suficientes recipientes enteros.

Comprueba dominios y comparaciones de números de coma flotante

math.sqrt(-1) lanza ValueError porque no hay una raíz cuadrada real para esa entrada. Los números de coma flotante calculados también requieren cuidado: su almacenamiento en binario hace que 0.1 + 0.2 == 0.3 sea False. math.isclose(0.1 + 0.2, 0.3) es True; úsalo para comparar de forma aproximada números de coma flotante calculados.

Selecciona la operación aleatoria

El módulo random utiliza un algoritmo para producir resultados pseudoaleatorios.

LlamadaResultado
random.randint(1, 6)Un entero de 1 a 6, ambos incluidos
random.randrange(1, 6)Un entero de 1 a 5
random.random()Un número de coma flotante mayor o igual que 0,0 y menor que 1,0
random.uniform(a, b)Un número de coma flotante entre los extremos indicados
random.choice(items)Un elemento
random.sample(items, k)Elementos de k posiciones, sin reemplazo
random.shuffle(items)Reordena la lista existente; devuelve None

Mantén random.shuffle(cards) en su propia línea. Asignar su resultado de nuevo a cards pierde la vinculación con la lista al sustituirla por None. Muestrear posiciones también es distinto de exigir valores diferentes: random.sample([1, 1], 2) devuelve [1, 1].

Ejecuta una simulación reproducible
import random

sevens = 0
for _ in range(1000):
    if random.randint(1, 6) + random.randint(1, 6) == 7:
        sevens += 1
print(sevens)

Seis de los 36 pares equiprobables suman 7, por lo que el recuento suele estar cerca de 167, pero cambia entre ejecuciones. Para reproducir una secuencia durante la depuración, llama a random.seed(42) antes de generar los valores, usando la misma versión de Python y la misma secuencia de llamadas. Para contraseñas o tokens de seguridad, usa secrets.

Encuentra otras herramientas de uso habitual

statistics.mean([2, 4, 9]) devuelve 5; statistics.median([2, 4, 9]) devuelve 4. datetime.date.today() da la fecha de hoy. Después de import sys, sys.argv contiene el nombre del archivo de programa seguido de sus argumentos: ejecutar python greet.py Ada proporciona ['greet.py', 'Ada'].

Puntos clave

  • floor, ceil, int y round resuelven distintas necesidades de redondeo.
  • Usa math.isclose al comparar números de coma flotante calculados.
  • randint incluye ambos extremos; randrange excluye su límite de parada.
  • sample selecciona posiciones sin reemplazo, por lo que los valores duplicados de la entrada pueden repetirse.
  • shuffle modifica la lista original y devuelve None.
  • Una semilla fija ayuda a reproducir el comportamiento aleatorio; los tokens de seguridad requieren secrets.

1.3 Haz que un archivo sea reutilizable sin iniciar su programa

Una función es más fácil de reutilizar cuando está en un módulo centrado en una tarea. Otro programa puede importar esa función, y una prueba puede comprobarla sin pedir a una persona que ejecute toda la aplicación.

Separa la función del código que la llama

Guarda este código como geometry.py:

"""Calculations for simple shapes."""
import math

def circle_area(radius):
    """Return the area of a circle with the given radius."""
    return math.pi * radius ** 2

En la misma carpeta, guarda este código que realiza la llamada como main.py:

import geometry

print(geometry.circle_area(2))

Ejecuta python main.py. Python encuentra geometry, crea su función y después el código que realiza la llamada ejecuta esa función. El resultado mostrado es 12.566370614359172. Importa sin la terminación .py. Un nombre de módulo válido usa letras, dígitos y guiones bajos con un primer carácter válido; my_tools.py funciona con import my_tools, mientras que import my-tools es sintaxis no válida.

Las cadenas situadas al principio del módulo y de la función son cadenas de documentación. Describen el propósito del código y aparecen en help(geometry) y help(geometry.circle_area).

Comprende qué ejecuta una importación

En la primera importación, Python ejecuta por orden las sentencias de nivel superior del módulo. Una sentencia def crea una función; no ejecuta el cuerpo de esa función. Sin embargo, un print(circle_area(2)) sin condición de protección al final de geometry.py mostraría su salida durante la importación.

Ese efecto secundario importa cuando un módulo contiene solicitudes de datos o un bucle del programa. Una prueba que solo necesita circle_area no debería tener que iniciar el programa y responder a sus solicitudes.

Protege el inicio y mantén disponible la función

Añade esto debajo de la función reutilizable en geometry.py:

def main():
    print(circle_area(2))

if __name__ == "__main__":
    main()

Python establece __name__ para cada módulo. Una ejecución directa, python geometry.py, lo establece en "__main__", por lo que la condición es verdadera y se llama a main(). Importar geometry lo establece en "geometry", así que Python omite la llamada. Las definiciones situadas antes de la condición de ejecución directa siguen disponibles en ambos casos.

No coloques la propia circle_area dentro de la condición de ejecución directa. El código que importa necesita esa definición incluso cuando la condición de inicio es falsa. La condición controla cuándo se inicia la aplicación; no impide que Python cargue el módulo.

Conoce dónde busca Python

Python comprueba módulos integrados como sys y después las carpetas de sys.path, por orden. Normalmente, la carpeta del archivo de programa en ejecución aparece primero en esa ruta, seguida de las carpetas de la biblioteca estándar y de los paquetes instalados. Mantener tus propios archivos junto al archivo de programa que ejecutas es una organización sencilla para un proyecto de principiante. Una importación normal no puede encontrar un módulo situado fuera de la ruta de búsqueda.

Este orden también puede ocultar un módulo de biblioteca. Si guardas tu programa como random.py, su import random puede cargar tu archivo en lugar de la biblioteca. Una llamada posterior a random.randint(1, 6) lanza entonces AttributeError. Cambia el nombre del archivo, por ejemplo, a dice.py; Python 3.13 y versiones posteriores pueden incluir en el error una sugerencia para cambiar el nombre.

Un módulo cargado se reutiliza dentro de la misma ejecución. En una consola interactiva, editar el archivo y volver a importarlo mantiene la versión cargada. Reinicia la consola antes de probar tus cambios.

Puntos clave

  • Importa tu propio archivo .py usando su nombre de módulo sin la extensión.
  • Una importación ejecuta las sentencias de nivel superior, mientras que los cuerpos de las funciones esperan a las llamadas.
  • Mantén las definiciones reutilizables fuera de la condición de ejecución directa __main__ y el inicio del programa dentro.
  • Un archivo local puede ocultar un módulo de biblioteca con el mismo nombre.
  • Reinicia la consola interactiva para probar desde cero un módulo editado.

1.4 Instala paquetes para el Python que ejecutas

Los paquetes de terceros añaden código que no viene con Python. PyPI, el Python Package Index en https://pypi.org, aloja estos proyectos. pip los descarga e instala para una instalación concreta de Python.

Usa la terminal y después Python

Un comando de terminal y una sentencia de Python se escriben en lugares distintos. El indicador >>> significa que estás en la consola interactiva de Python. Introducir pip install requests allí genera SyntaxError; Python no puede interpretarlo como una sentencia.

En tu terminal, ejecuta:

python -m pip install cowsay

Después, pon esto en un programa de Python:

import cowsay

cowsay.cow("Hello, Ada")

El programa muestra una vaca hecha con texto junto a un globo de diálogo que contiene el mensaje. La instalación hace que el paquete esté disponible; la importación crea la vinculación del programa con él.

Haz que pip corresponda a tu intérprete

La forma -m pip pide al Python indicado que ejecute su propio pip. Usa el comando que inicia tus programas: a menudo, python3 en macOS o Linux, o py en Windows.

python3 -m pip install cowsay
python3 game.py

Ambas líneas seleccionan el mismo comando de Python. Si una instalación informa de que ha terminado correctamente, pero un archivo de programa sigue lanzando ModuleNotFoundError, compara el Python usado para instalar con el usado para ejecutar el archivo. Un editor puede haber seleccionado un intérprete distinto del de tu terminal. Usa el pip del intérprete seleccionado antes de cambiar la importación.

Inspecciona y mantén una instalación
Comando de terminalTarea
python -m pip listEnumerar los paquetes instalados y sus versiones
python -m pip show requestsMostrar detalles, incluida su ubicación de instalación
python -m pip install --upgrade requestsActualizar a la versión más reciente disponible
python -m pip install "requests==2.32.3"Seleccionar esa versión exacta
python -m pip uninstall requestsEliminar el paquete

Una versión exacta resulta útil cuando necesitas el comportamiento de esa versión concreta. show ayuda a comprobar qué ubicación ha modificado realmente pip.

Comprueba el nombre en la documentación

El nombre de distribución escrito para pip puede diferir del nombre de importación. Instala beautifulsoup4 y después usa import bs4; instala Pillow y después usa import PIL. Instalar repetidamente un nombre de importación no es una solución útil cuando la documentación indica otra distribución.

La biblioteca estándar de Python, incluidos math, random y unittest, ya viene con Python. Estos módulos no requieren una instalación con pip.

Respeta una instalación gestionada

Algunos sistemas operativos y gestores de paquetes protegen su Python con un error externally-managed-environment. Esto significa que se bloquea la instalación directa para mantener la coherencia de la instalación gestionada. Usa un entorno virtual, una carpeta independiente con Python y paquetes para el proyecto. No fuerces la instalación con sudo pip install.

Cualquiera puede publicar en PyPI. Antes de instalar, comprueba la escritura exacta del nombre y lee la página y la documentación del proyecto. Los nombres parecidos pueden ser intentos de suplantación mediante nombres similares. Da preferencia a paquetes consolidados que reciban mantenimiento e instala los que tu programa necesita realmente.

Puntos clave

  • Ejecuta los comandos de pip en una terminal y las importaciones en el código Python.
  • Usa python -m pip con el mismo comando de intérprete que ejecuta el programa.
  • Consulta el nombre de importación en la documentación; puede diferir del nombre de instalación.
  • Usa pip para inspeccionar, actualizar, seleccionar una versión o eliminar un paquete.
  • Un Python gestionado puede requerir un entorno virtual para el proyecto.
  • Comprueba la escritura del nombre del paquete y su documentación antes de instalar código de terceros.
2

Lee errores y trazas de excepciones

La salida de error de Python registra tanto la operación que ha fallado como las llamadas que han llegado a ella. Leer esas pistas en orden te ayuda a encontrar un punto de partida útil, en lugar de cambiar la primera línea que reconozcas. Seguirás una traza hasta su entrada, distinguirás tipos habituales de excepción y reconocerás el caso menos evidente en el que un programa se ejecuta con normalidad, pero produce un resultado incorrecto. El comportamiento esperado te da algo concreto que comprobar.

2.1 Sigue una traza de excepción hasta la entrada incorrecta

Una traza de excepción indica qué llamadas estaban activas cuando una excepción no manejada detuvo el programa. Ofrece tanto un lugar por el que empezar a leer como un camino de vuelta hacia el valor que causó el fallo.

Empieza por la última línea

Considera este programa completo en scores.py:

def average(values):
    return sum(values) / len(values)

def report(scores):
    avg = average(scores)
    print(f"Average: {avg:.1f}")

report([])

La última línea de su informe de error es ZeroDivisionError: division by zero. Indica el tipo de excepción y describe la operación que ha fallado. Empieza ahí y después lee hacia arriba hasta la ubicación del código inmediatamente anterior.

Una traza simplificada, sin las marcas de expresión, es:

Traceback (most recent call last):
  File "scores.py", line 8, in <module>
    report([])
  File "scores.py", line 5, in report
    avg = average(scores)
  File "scores.py", line 2, in average
    return sum(values) / len(values)
ZeroDivisionError: division by zero
Lee cada marco como una llamada activa

Un marco de ejecución indica el archivo, el número de línea y la función, seguidos del código correspondiente. in <module> significa código de nivel superior. La llamada más antigua está arriba; la más reciente, abajo. Leer desde abajo invierte ese orden para que puedas averiguar qué ha fallado antes de preguntar cómo ha llegado allí la ejecución.

  1. La línea 2 divide entre len(values). Para que ese divisor sea cero, values debe estar vacío.
  2. La línea 5 llama a average(scores), así que inspecciona el scores que pasa report.
  3. La línea 8 proporciona [], la lista vacía. Eso explica cómo ha llegado el divisor cero al cálculo.

La línea que falla y la causa están relacionadas, pero pueden encontrarse en lugares distintos. Sustituir la división sin decidir qué debe significar una lista vacía ocultaría la cuestión de diseño. El código que realiza la llamada debe evitar una lista vacía o la función necesita un comportamiento definido para una entrada vacía.

Usa las marcas sin depender de su forma exacta

Python 3.11 y versiones posteriores pueden añadir marcas ^ y ~ para mostrar la parte de una expresión que falla. Ayudan cuando una línea contiene varias operaciones. Las marcas exactas varían entre versiones, pero las ubicaciones de las llamadas y el mensaje de excepción siguen indicando el orden de lectura.

Una traza puede contener marcos de la biblioteca estándar o de un paquete instalado. Busca el marco más bajo de tu propio código e inspecciona los argumentos que has proporcionado allí. Un marco de biblioteca es una pista de ubicación; no demuestra que la biblioteca contenga el error.

Reconoce un informe de sintaxis

Un error de sintaxis en el archivo de programa que se inicia impide que ese archivo se ejecute. Python informa de un archivo, una línea, una marca y un mensaje sin la cabecera habitual de la traza. Por ejemplo, a if True le faltan los dos puntos; total = sum([1, 2, 3] deja un paréntesis abierto.

El lugar marcado es donde Python ha detectado que no podía analizar el código. Cuando esa línea parece válida, revisa la anterior en busca de una comilla o un paréntesis sin cerrar. No hay una cadena de llamadas en ejecución que seguir cuando el archivo de programa inicial no ha llegado a ejecutarse.

Una ejecución normal se detiene en su primera excepción no manejada. Corrige ese problema y vuelve a ejecutar para descubrir cualquier problema posterior del programa.

Puntos clave

  • Lee primero el tipo de excepción y el mensaje, después el marco que falla y las llamadas que lo han originado.
  • Los marcos van desde la llamada activa más antigua, arriba, hasta la más reciente, abajo.
  • Sigue el valor incorrecto hacia atrás; su origen puede ser anterior al fallo.
  • Un error de sintaxis en el archivo de programa inicial se comunica antes de que ese archivo se ejecute.

2.2 Distingue entre un nombre, un tipo, un valor y un resultado incorrectos

El nombre de un error acota la búsqueda, y su mensaje añade detalles sobre los valores implicados. Un programa también puede ser incorrecto sin lanzar una excepción, por lo que comprobar la salida esperada sigue siendo parte de la detección de errores.

Distingue tres tipos de problema
TipoQué ocurreEjemplo
Error de sintaxisPython no puede analizar el códigoFaltan dos puntos después de if
Error de ejecuciónLa ejecución llega a una operación no válidaDividir entre cero
Error lógicoLa ejecución termina con un comportamiento incorrectoUn bucle omite un precio

IndentationError es un tipo de SyntaxError. El cuerpo de una función necesita sangría; la ausencia de un bloque con sangría detiene el código antes de que se ejecute. Revisa también las comillas o los paréntesis sin cerrar y las palabras reservadas mal escritas.

Lee con atención los nombres y los tipos

Un NameError significa que el programa no conoce un nombre en ese punto. En prnt("hi"), la función incorporada que se pretendía usar es print. También puede haberse usado un nombre antes de asignarle un valor o puede faltar una importación.

Un TypeError significa que una operación ha recibido un tipo inadecuado o que una llamada ha recibido un número incorrecto de argumentos. "Age: " + 30 mezcla una cadena y un entero. Escribe "Age: " + str(30) o f"Age: {30}". Si area necesita w y h, area(3) también genera TypeError, esta vez porque falta un argumento.

El mensaje distingue estas causas. En can only concatenate str (not "int") to str, Python indica los tipos que se han combinado. Después de age = input("Age: "), age es texto. age + 1 falla; para una entrada que representa un entero, int(age) + 1 realiza una operación aritmética.

Un ValueError significa que se acepta el tipo de la entrada, pero su valor no es adecuado. int("12.5") recibe una cadena, que es un tipo de entrada aceptado, pero el texto no representa un número entero con la forma requerida. math.sqrt(-1) es otro valor inadecuado para un cálculo con números reales.

Comprueba posiciones, claves y atributos
ExcepciónEjemploCausa
IndexError[4, 6, 10][3]El último índice válido es 2
KeyError{"apples": 3}["pears"]El diccionario no tiene "pears"
ZeroDivisionError10 / 0El divisor es cero
AttributeErrormath.sqroot(16)El módulo no tiene sqroot
ModuleNotFoundErrorimport mathhNo se encuentra ningún módulo con ese nombre
ImportErrorfrom math import square_rootEl módulo no tiene ese nombre importado

Los divisores cero también provocan fallos con // y %. Buscar una posición inexistente en una lista es distinto de buscar una clave inexistente en un diccionario, aunque ambos casos impliquen solicitar algo que no está.

Detecta un resultado que parece razonable
def total_price(prices):
    total = 0
    for i in range(1, len(prices)):
        total += prices[i]
    return total

Para [4, 6, 10], esto devuelve 16 en lugar de 20. No hay ninguna excepción: los índices 1 y 2 existen, así que todas las operaciones son válidas. El bucle empieza demasiado tarde y omite el índice 0. El error se hace visible al comparar la salida con el total previsto.

Para una excepción que no conozcas, busca su tipo y el mensaje general en la documentación oficial de Python. Elimina de la búsqueda tus propias rutas y valores de entrada; rara vez explican la regla general.

Puntos clave

  • Los errores de sintaxis impiden analizar el código; los de ejecución ocurren al ejecutarlo; los lógicos producen un comportamiento incorrecto.
  • NameError se refiere a una vinculación; TypeError, a un tipo o a los argumentos de una llamada.
  • ValueError se refiere a un valor inadecuado proporcionado con un tipo aceptado.
  • IndexError, KeyError y AttributeError se refieren a distintos tipos de consulta.
  • Comparar la salida con un resultado esperado puede revelar un error lógico sin traza de excepción.
3

Encuentra la causa de un error de programación

Un resultado incorrecto es más fácil de investigar cuando puedes reproducirlo y decir exactamente en qué difiere del resultado esperado. Convertirás esa observación en una suposición comprobable, acotarás la búsqueda a un pequeño fragmento de código e inspeccionarás los valores relevantes. Las llamadas a print, las tablas de seguimiento y los controles del depurador ofrecen distintas formas de observar la ejecución. Después de una corrección concreta, comprobar los casos que antes funcionaban ayuda a detectar cualquier comportamiento afectado por el cambio.

3.1 Comprueba una causa antes de cambiar el código

Un error de programación es una diferencia entre el comportamiento previsto y el real. La depuración encuentra la causa y la corrige. Una sesión de depuración útil convierte una observación en una explicación comprobable y después modifica el código basándose en pruebas.

Haz que el fallo se repita

Registra una entrada concreta y el resultado que produce. Para la función de precios que empieza su bucle en el índice 1, usa [4, 6, 10]. El total esperado es 20; el total real es 16. Estos valores concretos permiten comprobar si cada investigación sigue tratando el mismo error.

La diferencia es 4, y el resultado real equivale a 6 + 10. Una hipótesis concreta es que se omite el primer precio. Esa hipótesis predice algo que puedes inspeccionar: el bucle nunca visitará el índice 0.

Sigue seis pasos
  1. Reproduce: encuentra una entrada que muestre el error de forma fiable.
  2. Indica los resultados esperado y real: calcula el resultado esperado de forma independiente.
  3. Formula una hipótesis: indica una causa posible y el comportamiento que predice.
  4. Compruébala: inspecciona los valores con llamadas a print, una tabla de seguimiento o un depurador.
  5. Corrige la causa: realiza un cambio concreto.
  6. Vuelve a probar: ejecuta la entrada que fallaba y los casos que antes funcionaban.

Muestra el índice dentro del bucle. Para esta entrada, los únicos índices son 1 y 2, lo que confirma la predicción. Iniciar range en 0 corrige la omisión del elemento. Recorrer directamente los precios elimina la necesidad de gestionar un índice:

def total_price(prices):
    total = 0
    for price in prices:
        total += price
    return total

La función corregida devuelve 20 para [4, 6, 10], 5 para [5] y 0 para []. El caso de un elemento es útil porque el bucle con el error devolvía antes 0 para él.

Sumar 4 a todas las respuestas corregiría el total observado, pero dejaría la causa. Para [5], ese parche devolvería 4; la cantidad que falta depende de la entrada. Comprueba si una solución propuesta explica todas las pruebas observadas antes de conservarla.

Acota una búsqueda más amplia

Divide y vencerás comprueba los valores que intervienen en el resultado incorrecto en un punto intermedio de la ejecución. Si un valor necesario ya es incorrecto, inspecciona el código anterior que lo ha producido. Si los valores necesarios siguen siendo correctos, sigue su procesamiento posterior. Repite el proceso dentro de la sección restante.

También puedes llamar a una función por separado o eliminar temporalmente código no relacionado. Un ejemplo mínimo reproducible conserva el código más breve y la entrada más pequeña que siguen fallando. Para un problema detectado inicialmente entre cientos de registros, encontrar uno o dos registros que lo desencadenen facilita cada inspección.

Comprueba qué son realmente los datos

Un 5 mostrado puede ser la cadena "5". "5" + "3" produce "53", mientras que la suma numérica da 8. Inspecciona type(value) para comprobar el tipo. Usa repr(value) para revelar espacios y caracteres de salto de línea que una salida normal puede ocultar, como ' Ada'.

Explica el código en voz alta, línea por línea, incluido qué visita realmente cada bucle y qué devuelve cada función. Esto es la depuración con un patito de goma: explicar un paso suele revelar la diferencia entre la operación prevista y la escrita.

Cambia una causa cada vez para poder relacionar el resultado con la modificación. Vuelve a probar tanto los casos que antes funcionaban como el que fallaba.

Puntos clave

  • Reproduce el error y registra los resultados esperado y real antes de editar.
  • Una hipótesis útil predice algo que puedes inspeccionar.
  • Corrige la causa con un cambio y después vuelve a probar los casos que fallaban y los que antes funcionaban.
  • Usa un ejemplo mínimo o valores intermedios para acotar la búsqueda.
  • Comprueba los tipos y los caracteres ocultos cuando el aspecto de los valores resulte engañoso.

3.2 Observa cómo cambian los valores con llamadas a print y un depurador

La respuesta final de un programa oculta el camino que la ha producido. Las llamadas temporales a print, una tabla de seguimiento y un depurador permiten ver ese camino y comprobar una hipótesis concreta sobre dónde falla.

Muestra un valor en un momento conocido

Etiqueta la salida de diagnóstico para que un número tenga un significado claro. Python 3.8 y versiones posteriores admiten esta forma de cadena formateada:

print(f"{i=} {total=}")

Para el bucle de precios con el error, colócala inmediatamente antes de total += prices[i]. Con los precios [4, 6, 10], muestra:

i=1 total=0
i=2 total=6

Estos son los totales antes de cada suma. Después de la primera salida, el bucle suma 6; después de la segunda, suma 10. Una llamada a print después de la suma mostraría totales distintos. Decide qué momento responde a lo que quieres averiguar antes de interpretar la salida.

Sigue el mismo código a mano

Una tabla de seguimiento registra las variables paso a paso. Para este bucle:

Índice iPrecio sumadoTotal antesTotal después
1606
210616

No hay ninguna iteración para el índice 0. Sigue los valores reales de inicio y parada escritos en el código, incluso cuando ya sepas qué debería hacer el bucle. Una tabla ayuda a separar lo que esperas de lo que ocurre.

Pausa en un punto de interrupción

Un depurador pausa un programa en ejecución para que puedas inspeccionar su estado actual. Un punto de interrupción marca un lugar donde detenerse. En editores como Thonny y VS Code, haz clic junto a un número de línea e inicia el modo de depuración; en IDLE, haz clic derecho en la línea y elige Establecer punto de interrupción.

Después de pausar, elige un paso según lo que estés investigando:

ControlEfecto
Paso a paso por procedimientosEjecutar la línea actual, incluida una función llamada
Paso a paso por instruccionesEntrar en una función llamada en esa línea
Salir de la funciónTerminar esta función y pausar después del retorno
ContinuarEjecutar hasta otro punto de interrupción o el final del programa

Si el código que realiza la llamada pasa argumentos correctos, pero recibe una respuesta incorrecta, entra en la función. Si solo necesitas ver el resultado devuelto, ejecuta la llamada como un solo paso. Inspecciona los valores antes y después de la línea que podría crear el error.

Usa el depurador de texto de Python

Inserta breakpoint() justo antes del código que quieras inspeccionar. Con la configuración predeterminada del depurador, ejecutar el programa inicia pdb en ese punto. Escribe estos comandos en su indicador (Pdb):

  • p total muestra total.
  • n ejecuta la siguiente línea sin entrar en sus llamadas.
  • s entra en una llamada a función.
  • c continúa la ejecución.
  • q sale de la sesión de depuración.

Son comandos del depurador, no líneas para copiar en tu programa.

Distingue la salida mostrada de los resultados devueltos

Una función puede mostrar el número correcto y aun así devolver None porque le falta return total. Inspecciona el valor recibido por el código que realiza la llamada cuando el fallo ocurre después de llamar a la función. Ver una salida correcta dentro de la función no demuestra que el código que la llama haya recibido ese número.

Usa llamadas a print para obtener pistas rápidas a lo largo de las iteraciones de un bucle y el depurador para inspeccionar un momento concreto. Después de corregir el error, elimina las llamadas temporales a print y a breakpoint() para que el programa terminado se ejecute con normalidad.

Puntos clave

  • Etiqueta las salidas de depuración e indica si se ejecutan antes o después de una actualización.
  • Una tabla de seguimiento sigue los cambios reales de las variables paso a paso.
  • Los puntos de interrupción pausan la ejecución; los controles de avance determinan cuánto código se ejecuta a continuación.
  • breakpoint() abre pdb de forma predeterminada; p, n, s, c y q son comandos del depurador.
  • Inspecciona los valores devueltos cuando una función muestra la salida correcta, pero el código que la llama falla.
  • Elimina la salida de diagnóstico temporal y los puntos de interrupción después de corregir el error.
4

Comprueba tus funciones con pruebas

Las comprobaciones automatizadas permiten repetir un ejemplo útil cada vez que cambia una función. Escribirás aserciones con expectativas claras, elegirás entradas que alcancen los límites de una regla y evitarás que las pruebas inicien la aplicación que importan. Después, el marco estándar unittest da a cada prueba un nombre y un resultado independiente. Leer sus fallos y errores conecta las pruebas con la depuración: la prueba reproduce un problema y la investigación encuentra su causa.

4.1 Escribe comprobaciones que fallen cuando un supuesto sea falso

Una aserción expresa algo que debe ser verdadero si tu código funciona correctamente. Puede detener un error cerca de donde empieza o comparar el resultado de una función con el valor que esperas.

Escribe una condición y un mensaje opcional
assert letter_grade(90) == "A", "90 should be an A"

Python evalúa la condición. Si letter_grade(90) devuelve "A", la condición es verdadera y la ejecución continúa sin salida. Si devuelve "B", Python lanza AssertionError con el mensaje 90 should be an A. La traza señala la comprobación que falla.

Sin el mensaje, assert letter_grade(90) == "A" sigue comprobando el resultado. La última línea de la excepción contiene AssertionError, mientras que la traza muestra la expresión. Un mensaje útil indica la expectativa que no se ha cumplido; debe ayudarte a localizar la regla que se comprueba.

Detén pronto un error interno

Supón que un cálculo interno requiere una lista no vacía:

def average(values):
    assert len(values) > 0, "values must not be empty"
    return sum(values) / len(values)

Una lista vacía activa ahora la aserción antes de la división. La comprobación documenta el supuesto interno de la función y señala directamente su incumplimiento. No da una media a una lista vacía ni decide cómo debe responder una aplicación cuando faltan datos de un usuario.

Mantén activa la validación de datos del usuario

La opción -O de Python elimina las sentencias assert. Por tanto, un programa que dependa de una aserción para rechazar una entrada externa puede comportarse de forma distinta al optimizarse. Comprueba los datos del usuario y otros datos externos con el flujo de control habitual:

def require_score(score):
    if score < 0 or score > 100:
        raise ValueError("score must be 0 to 100")
    return score

Aquí raise ValueError(...) comunica un valor inadecuado. La sentencia if sigue ejecutándose con -O. Elige una aserción para un supuesto interno de programación y una comprobación de entrada activa para datos externos que puedan ser incorrectos.

Evita una comprobación que nunca pueda fallar

assert es una sentencia, no una función. Escribe la condición y el mensaje separados por una coma:

assert x > 10, "x too small"

Escribir assert (x > 10, "x too small") crea una tupla de dos elementos. Una tupla no vacía es verdadera incluso cuando su primer elemento es False, por lo que la aserción se cumple. Python puede avisar de que esta aserción siempre es verdadera. Los paréntesis que rodean solo una condición, como en assert (x > 10), no crean esa tupla; el problema es la coma dentro de los paréntesis.

Usa == para comparar. assert total = 20 es sintaxis no válida porque = asigna un valor.

Compara números con la precisión prevista

Para un número de coma flotante calculado, usa una comprobación de proximidad:

import math

assert math.isclose(0.1 + 0.2, 0.3)

Una comparación exacta falla aquí porque la suma almacenada en coma flotante difiere ligeramente de 0.3. Una prueba automatizada sencilla aplica la misma idea de aserción a una función: assert total_price([4, 6, 10]) == 20. El valor esperado procede de la regla de la función, por lo que la comprobación puede revelar una implementación incorrecta.

Puntos clave

  • assert condition, message lanza AssertionError cuando su condición es falsa.
  • Las aserciones pueden comprobar supuestos internos y resultados esperados de funciones.
  • Usa if y un mensaje de error o una excepción para la entrada externa; -O elimina las aserciones.
  • Una coma dentro de assert (condition, message) crea una tupla considerada verdadera.
  • Usa == para la igualdad y math.isclose para comparar números de coma flotante calculados.

4.2 Elige pruebas que puedan revelar un error de programación

Una prueba unitaria comprueba una pequeña unidad de código, normalmente una función, con una entrada elegida y un resultado esperado. Las pruebas automatizadas facilitan repetir las mismas comprobaciones después de editar el código y ayudan a detectar errores que reaparecen en comportamientos que antes funcionaban.

Empieza por la especificación

Supón que una función de calificación debe devolver "A" para puntuaciones de al menos 90, "B" para puntuaciones de al menos 80 pero inferiores a 90, y "C" por debajo de 80. La primera condición, que contiene el error, es score > 90.

Las pruebas deben cumplir varias funciones:

  • Los casos típicos comprueban entradas habituales dentro de cada tramo, como 95 y 85.
  • Los casos en los límites comprueban los valores donde cambia una regla, como 90 y 89, u 80 y 79.
  • Los casos límite comprueban entradas como cero o una colección vacía cuando las reglas de la función las permiten.

Calcula la respuesta esperada a partir de esas reglas. Copiar la respuesta actual del programa en una prueba puede conservar su error.

Coloca las pruebas junto al módulo

Guarda las pruebas en test_grade.py y la función en grade.py. El inicio de la aplicación en grade.py debe estar dentro de su condición de ejecución directa __main__, para que importar la función no inicie el programa.

from grade import letter_grade

def test_letter_grade():
    assert letter_grade(95) == "A"
    assert letter_grade(90) == "A"
    assert letter_grade(85) == "B"

Con la regla que contiene el error, la primera aserción se cumple. La segunda falla porque 90 no es mayor que 90; la ejecución se detiene ahí, antes de la tercera aserción de esta función. Cambiar la primera condición a score >= 90 corrige este límite. Vuelve a ejecutar todas las pruebas para comprobar el caso afectado y el comportamiento anterior.

Asegúrate de que las pruebas se ejecuten realmente

Definir una función de prueba no la llama. Si no usas un ejecutor de pruebas, añade test_letter_grade() al final del archivo de pruebas y después ejecuta python test_grade.py. Para usar pytest, instálalo con python -m pip install pytest y después ejecuta pytest test_grade.py en la terminal. Encuentra las funciones de prueba e informa de sus resultados. Omite las llamadas manuales cuando dejes que un ejecutor las gestione.

Una prueba que solo llama a letter_grade(90) no incluye ninguna comparación. Puede terminar correctamente aunque la respuesta devuelta sea incorrecta; solo falla si la llamada lanza una excepción inesperada. Una aserción conecta la llamada con el comportamiento requerido.

Prueba valores devueltos y propiedades de resultados aleatorios

Una función que solo muestra un total devuelve None. Por tanto, una comparación como assert print_total([4, 6]) == 10 falla aunque la pantalla muestre 10. Haz que el cálculo devuelva su respuesta y deja que main se encargue de mostrarla.

Los resultados aleatorios necesitan una expectativa distinta. No se puede exigir que una función de dado sin semilla devuelva una cara exacta en cada llamada. Comprueba que cada una de 100 llamadas devuelva un valor permitido de 1 a 6, o establece una semilla antes de generar una secuencia reproducible. Superar la prueba de límites comprueba los límites para esas llamadas; no demuestra que todas las caras sean igual de probables.

Cuando aparezca un error nuevo, añade una prueba que falle por ese error antes de corregir la función. Conserva esa prueba de regresión para que las modificaciones posteriores vuelvan a comprobar el mismo comportamiento. Las pruebas que pasan demuestran lo que ha ocurrido en los casos probados; otras entradas aún pueden revelar otro error.

Puntos clave

  • Elige los resultados esperados a partir de la especificación, con independencia de la implementación.
  • Prueba entradas habituales, límites de las reglas y casos límite relevantes.
  • Las funciones de prueba necesitan una llamada o un ejecutor; las definiciones por sí solas no realizan comprobaciones.
  • Las aserciones deben comparar los resultados devueltos con el comportamiento previsto.
  • Prueba propiedades adecuadas de la salida aleatoria o prepara una secuencia reproducible.
  • Conserva una prueba para cada error nuevo que encuentres para ayudar a detectar regresiones.

4.3 Ejecuta e interpreta un archivo de pruebas de unittest

Python incluye unittest, un marco de pruebas que detecta pruebas, las ejecuta e informa de sus resultados por separado. No necesita instalación con pip. Puedes usar su estructura de clases como plantilla mientras aprendes a probar funciones.

Escribe métodos de prueba independientes

Para una función de grade.py, coloca esto en test_grade.py:

import unittest
from grade import letter_grade

class TestLetterGrade(unittest.TestCase):
    def test_top(self):
        self.assertEqual(letter_grade(95), "A")

    def test_boundary(self):
        self.assertEqual(letter_grade(90), "A")

    def test_low(self):
        self.assertEqual(letter_grade(50), "C")

if __name__ == "__main__":
    unittest.main()

TestLetterGrade hereda las herramientas de prueba de unittest.TestCase. Cada prueba es un método cuyo nombre empieza por test. self identifica el objeto de prueba actual; mantenlo en la lista de parámetros de cada método y antes de las llamadas a métodos de aserción. Puedes copiar esta estructura sin diseñar tus propias clases.

De forma predeterminada, las pruebas se ejecutan por orden alfabético de sus nombres de método, así que test_boundary va antes de test_low y test_top. Haz que cada prueba proporcione su propia entrada necesaria y funcione con independencia de las pruebas anteriores.

Elige un método de aserción
MétodoComprobación
self.assertEqual(actual, expected)Los valores son iguales
self.assertNotEqual(a, b)Los valores son distintos
self.assertTrue(condition)Una condición es verdadera
self.assertFalse(condition)Una condición es falsa
self.assertIn(item, collection)El elemento pertenece a la colección
self.assertAlmostEqual(a, b)La diferencia redondeada a 7 decimales es cero, de forma predeterminada

Da preferencia a assertEqual(a, b) frente a assertTrue(a == b) al comparar valores: el informe de fallo muestra ambos valores. Los métodos de unittest también mantienen sus comprobaciones cuando Python se ejecuta con -O.

Para comprobar una excepción esperada, encierra la llamada en assertRaises:

def test_score_too_high(self):
    with self.assertRaises(ValueError):
        letter_grade(120)

Esta prueba exige que la regla de la función rechace esa puntuación con ValueError. Un retorno sin excepción hace fallar esta comprobación; una excepción distinta que no sea de aserción se considera un error.

Ejecuta y lee el informe

Ejecuta python test_grade.py para ejecutar su unittest.main() protegido por la condición de ejecución directa. O ejecuta python -m unittest para detectar archivos test*.py en la carpeta actual. python -m unittest -v muestra los nombres de las pruebas y sus resultados individuales.

En el informe breve, . significa que la prueba pasa, F que una aserción ha fallado y E que se ha producido otra excepción. Para una función de calificación con score > 90, las tres pruebas anteriores producen F... El informe de fallo de test_boundary muestra 'B' != 'A': el resultado real es "B", mientras que el esperado es "A". El resumen indica tres pruebas y un fallo.

Antes de editar la función, contrasta la expectativa de la prueba con las reglas de calificación. Una expectativa incorrecta requiere corregir la prueba. Si no se ejecuta ninguna prueba, revisa los nombres de los métodos, la condición de ejecución directa y el comando de inicio. Evita también llamar a tu archivo unittest.py, ya que oculta el módulo estándar.

Puntos clave

  • Coloca métodos test dentro de una clase que herede de unittest.TestCase.
  • Usa self.assertEqual y otros métodos de aserción para obtener comprobaciones e informes claros.
  • assertRaises comprueba una excepción esperada; las comparaciones de números de coma flotante pueden usar assertAlmostEqual.
  • Ejecuta directamente un archivo de pruebas protegido por una condición de ejecución directa o usa python -m unittest para detectar pruebas.
  • Interpreta F como una aserción fallida y E como otra excepción.
  • Contrasta una prueba fallida con la especificación antes de cambiar la función.
  • Cada prueba debe funcionar con independencia del orden alfabético de ejecución.

Ejemplos de Módulos y depuración en Python

4 Lecciones Interactivas

1

Construye un programa con piezas reutilizables

20 pasos
Elige importaciones y funciones de biblioteca, reutiliza tu propio código y vincula los paquetes instalados con el Python que los ejecuta.
  1. 1
    IntroducciónEmpieza con código que puedas reutilizar

    Un programa puede llamar a código de la biblioteca estándar de Python, de otro archivo que hayas escrito o de un paquete instalado. La primera cuestión es qué nombre tiene disponible el programa después de importar.

    Seguirás un cálculo desde una importación hasta su valor devuelto y después organizarás un módulo reutilizable y vincularás la instalación de un paquete con su intérprete. Durante el proceso, comprueba si un resultado es un valor que conservas o un cambio realizado en una lista existente.

  2. 2
    ExplicaciónLa importación determina la forma de la llamada

    Estas importaciones permiten acceder a la misma función mediante vinculaciones distintas:

    import math
    print(math.sqrt(16))
    
    from math import sqrt
    print(sqrt(16))
    

    Ambas muestran 4.0. La primera crea math, así que la llamada usa un punto. La segunda crea sqrt, por lo que no necesita prefijo de módulo. Usar la forma de llamada incorrecta lanza NameError cuando ese nombre no se ha vinculado.

  3. 3
    EjemploCalcula la hipotenusa

    Con import math, para un triángulo rectángulo con catetos de 3 y 4 puedes usar:

    length = math.sqrt(3**2 + 4**2)
    

    Los cuadrados son 9 y 16. Su suma es 25 y math.sqrt(25) devuelve 5.0. Python evalúa el argumento antes de llamar a la función.

    El prefijo también indica a quien lee el código de dónde procede sqrt. Una importación con comodín oculta ese origen y puede sustituir nombres existentes, como una variable llamada e.

  4. 4
    DesafíoSigue la vinculación del alias

    Un archivo de programa recién iniciado ejecuta estas líneas. ¿Qué ocurre en la última línea y cómo se puede corregir?

    import statistics as st
    print(statistics.mean([4, 8, 12]))
    

    ---reveal---

    Lanza NameError porque la importación vincula st, no statistics. Usa st.mean([4, 8, 12]), que devuelve 8. Un alias elige la vinculación en este programa; no crea además el nombre original del módulo.

  5. 5
    EjemploRedondea para obtener suficientes recipientes enteros

    Una pared necesita pintura para 23 metros cuadrados. Cada lata cubre 10 metros cuadrados.

    import math
    cans = math.ceil(23 / 10)
    

    La división da 2.3; ceil da 3, suficientes latas enteras. round(2.3) solo da 2.

    Para entradas negativas, hacia abajo sigue significando hacia menos infinito: math.floor(-2.5) es -3, mientras que int(-2.5) trunca hacia cero y da -2.

  6. 6
    Idea claveAdapta la comparación al número

    Los números de coma flotante calculados pueden diferir ligeramente de los valores decimales que se pretenden obtener:

    0.1 + 0.2 == 0.3               # False
    math.isclose(0.1 + 0.2, 0.3)   # True
    

    Usa una comprobación de proximidad para esa comparación aproximada. Además, las entradas permitidas por una función siguen siendo relevantes: math.sqrt(-1) lanza ValueError.

    La función incorporada round no necesita ninguna importación. Para un valor exactamente a mitad de camino, elige el vecino par: round(2.5) es 2 y round(3.5) es 4.

  7. 7
    ExplicaciónElige el resultado aleatorio que necesitas

    Después de import random, elige una llamada según su tarea:

    • randint(1, 6) elige un entero e incluye el 6.
    • randrange(1, 6) elige un entero y excluye el 6.
    • random() da un número de coma flotante desde 0,0 hasta 1,0, sin incluirlo.
    • choice(items) elige un elemento.
    • sample(items, k) elige k posiciones sin reemplazo.

    Dos posiciones seleccionadas pueden contener el mismo valor. Por tanto, muestrear [1, 1] en ambas posiciones da valores 1 repetidos.

  8. 8
    DesafíoConserva la lista mezclada

    ¿Qué valor contiene names al final y cómo debe cambiar la última línea para conservar la lista?

    names = ["Mina", "Luis", "Jo"]
    names = random.shuffle(names)
    

    ---reveal---

    Contiene None. shuffle modifica la lista existente y después devuelve None; la asignación sustituye la vinculación con la lista por ese valor de retorno. Usa random.shuffle(names) en su propia línea. El nuevo orden de la lista es aleatorio, pero lo que devuelve la función es fijo.

  9. 9
    ConexiónRepite una simulación y encuentra otras herramientas

    Llama a random.seed(42) antes de generar valores para repetir la misma secuencia con la misma versión de Python. Así resulta más fácil reproducir un fallo aleatorio. Usa secrets para tokens de seguridad.

    Otros módulos estándar resuelven tareas habituales: statistics.mean([2, 4, 9]) da 5 y median da 4. datetime.date.today() da la fecha de hoy. sys.argv enumera el nombre del archivo de programa en ejecución seguido de sus argumentos de línea de comandos.

  10. 10
    EjemploColoca una función reutilizable en un módulo

    Guarda esto como geometry.py:

    import math
    
    def circle_area(radius):
        """Return the circle's area."""
        return math.pi * radius ** 2
    

    Un archivo de programa de la misma carpeta puede ejecutar import geometry y después print(geometry.circle_area(2)). Muestra 12.566370614359172.

    Importa el archivo sin .py. La primera cadena de la función es su cadena de documentación, que help(geometry.circle_area) puede mostrar.

  11. 11
    ExplicaciónUna importación ejecuta las sentencias de nivel superior

    Supón que geometry.py termina con print(circle_area(2)), fuera de una función. Su primera importación muestra el área como efecto secundario.

    Python ejecuta las sentencias del nivel del módulo por orden. Definir circle_area crea la función sin ejecutar su cuerpo; llamarla dentro de la llamada a print de nivel superior ejecuta el cálculo. Una segunda importación en el mismo proceso reutiliza el módulo cargado. Una consola interactiva también conserva esa versión cargada después de editar el archivo, hasta que la reinicies.

  12. 12
    EjemploInicia el programa solo en una ejecución directa

    Deja la función reutilizable encima de este bloque:

    def main():
        print(circle_area(2))
    
    if __name__ == "__main__":
        main()
    

    Una ejecución directa establece __name__ en "__main__", así que se ejecuta main(). Una importación lo establece en "geometry", así que se omite el inicio.

    Las definiciones siguen disponibles en ambos casos. Esto permite que una prueba importe circle_area sin producir la salida habitual del programa.

  13. 13
    DesafíoMantén la función disponible para el código que la importa

    Un archivo define convert dentro de su bloque if __name__ == "__main__":. Un proceso de pruebas recién iniciado importa el archivo y no encuentra convert. ¿Qué organización permite tanto reutilizar la función como iniciar el programa en una ejecución directa?

    ---reveal---

    Mueve def convert(...) fuera de la condición de ejecución directa y deja solo el inicio del programa dentro. Durante la importación, la condición es falsa, así que se omite una definición situada dentro. Mover la definición hace que esté disponible sin iniciar la aplicación.

  14. 14
    ConsejoComprueba qué archivo encuentra una importación

    Python comprueba los módulos integrados y después busca en sys.path por orden. La carpeta del archivo de programa suele aparecer antes que las carpetas de bibliotecas. Por tanto, un random.py local puede ocultar el random que querías importar.

    Cambia el nombre de ese archivo a algo como dice.py. Para tus propias funciones auxiliares, usa nombres válidos como my_tools.py y mantenlas junto al archivo de programa de principiante que las importa. Una importación normal no encuentra un archivo situado fuera de la ruta de búsqueda.

  15. 15
    EjemploInstala en la terminal e importa en Python

    En la terminal, ejecuta:

    python -m pip install cowsay
    

    Después, el código Python puede usar:

    import cowsay
    cowsay.cow("Hello, Ada")
    

    El paquete muestra una vaca hecha con texto y un globo de diálogo. pip instala código, mientras que import crea la vinculación que usa tu programa. El comando de instalación no es una sentencia de Python; en un indicador >>> produce sintaxis no válida.

  16. 16
    ExplicaciónUsa el pip que pertenece al Python en ejecución

    Si un archivo de programa se ejecuta con python3, instala mediante el mismo comando:

    python3 -m pip install cowsay
    python3 game.py
    

    -m pip selecciona el pip que pertenece a ese intérprete. En Windows, tu comando puede ser py.

    Si el editor no puede importar un paquete instalado correctamente, compara su intérprete seleccionado con el usado en la terminal. Instalar correctamente en un Python no instala el paquete en todos los demás Python.

  17. 17
    DesafíoDistingue el nombre de instalación del nombre de importación

    La documentación de un paquete indica que debes instalar Pillow e importar PIL. La instalación se completa correctamente para el Python que ejecutas, pero import Pillow falla. ¿Qué debe cambiar y por qué?

    ---reveal---

    Usa import PIL. El nombre de distribución que usa pip puede diferir del nombre de importación de Python que proporciona. Como ya se ha comprobado que el intérprete coincide, repetir el mismo comando de instalación dejaría sin corregir este error concreto de nombre.

  18. 18
    ConsejoInspecciona un paquete antes de modificarlo

    python -m pip list muestra las versiones instaladas. show requests da la versión y la ubicación de un paquete; install --upgrade requests lo actualiza y uninstall requests lo elimina. Cada comando abreviado va después de python -m pip.

    Comprueba el nombre exacto en PyPI y la documentación del proyecto antes de instalar. Ante un error externally-managed-environment, usa un entorno virtual para el proyecto; no fuerces la instalación con sudo pip install.

  19. 19
    DesafíoPredice una importación y una llamada posterior

    Un módulo nuevo sizes.py contiene este código. Otro archivo de programa ejecuta from sizes import batches y después print(batches(17)). ¿Qué se muestra?

    import math
    
    def batches(n):
        return math.ceil(n / 5)
    
    if __name__ == "__main__":
        print(batches(12))
    

    ---reveal---

    Solo se muestra 4. La importación crea la función, pero omite la llamada a print protegida por la condición. La llamada posterior divide 17 entre 5 y después redondea 3,4 hacia arriba a 4. La vinculación math dentro de sizes está disponible para su función.

  20. 20
    RepasoSigue el código desde su origen hasta la llamada

    Elige una importación que coincida con los nombres que quieres usar. Comprueba qué devuelve una llamada de biblioteca, incluido un posible None de una operación que modifica una lista.

    Mantén las definiciones reutilizables disponibles durante la importación y coloca el inicio de la aplicación dentro de la condición de ejecución directa. Para el código instalado, haz que pip corresponda al intérprete en ejecución y comprueba el nombre de importación documentado. Cuando falla una llamada, estos detalles ayudan a distinguir una vinculación ausente, un atributo ausente y una instalación ausente.

2

Sigue un fallo hasta su causa

11 pasos
Lee marcos de llamadas, reconoce excepciones habituales y distingue un fallo que detiene el programa de un resultado incorrecto sin mensaje de error.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónUsa el informe como prueba
  2. 2
    EjemploUna lista vacía llega a una división
  3. 3
    ExplicaciónEncuentra el marco más reciente
  4. 4
    EjemploSigue el argumento hacia atrás a través de las llamadas
  5. 5
    DesafíoLocaliza un argumento inadecuado
  6. 6
    ExplicaciónDistingue gramática, tipos y valores
  7. 7
    ExplicaciónDistintas consultas generan distintos errores
  8. 8
    EjemploUn total incorrecto puede terminar con normalidad
  9. 9
    DesafíoExplica una suma fallida
  10. 10
    DesafíoUsa un marco de biblioteca sin culpar a la biblioteca
  11. 11
    RepasoElige el siguiente lugar que revisar
3

Investiga un error desde las pruebas hasta la corrección

14 pasos
Reproduce un total incorrecto, inspecciona su bucle, realiza una corrección concreta y usa los controles del depurador para seguir una llamada a función.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónHaz que se repita el resultado incorrecto
  2. 2
    EjemploIndica los resultados esperado y real
  3. 3
    ExplicaciónHaz que la suposición sea comprobable
  4. 4
    EjemploMuestra los valores antes de actualizar
  5. 5
    EjemploSigue las sumas a mano
  6. 6
    DesafíoInterpreta una salida posterior a la actualización
  7. 7
    EjemploCorrige la propia iteración
  8. 8
    ConexiónVuelve a probar entradas con distintas estructuras
  9. 9
    ConsejoReduce un caso de fallo más amplio
  10. 10
    DesafíoComprueba un valor que parece numérico
  11. 11
    ExplicaciónPausa en la llamada que necesitas inspeccionar
  12. 12
    DesafíoElige el comando de avance
  13. 13
    DesafíoInvestiga una salida correcta y un retorno incorrecto
  14. 14
    RepasoMantén la corrección vinculada a las pruebas observadas
4

Convierte un error en un límite en una prueba permanente

16 pasos
Escribe aserciones, elige entradas que revelen errores y usa unittest para ejecutar comprobaciones independientes e interpretar sus resultados.

Guarda esta unidad para seguir cada Lección Interactiva paso a paso.

  1. 1
    IntroducciónDa al comportamiento esperado una comprobación repetible
  2. 2
    ExplicaciónUna aserción expresa una expectativa
  3. 3
    DesafíoEncuentra una comprobación que no puede fallar
  4. 4
    Idea claveMantén activas las comprobaciones de entradas externas
  5. 5
    EjemploElige entradas alrededor del cambio de calificación
  6. 6
    EjemploEscribe una función de prueba que importe el código
  7. 7
    ConsejoEjecuta las comprobaciones que has definido
  8. 8
    DesafíoCorrige un umbral y conserva la comprobación
  9. 9
    ConexiónPrueba el resultado devuelto o una propiedad válida
  10. 10
    EjemploUsa la plantilla de clase de unittest
  11. 11
    ExplicaciónElige la aserción según el resultado
  12. 12
    EjemploLee una comprobación de calificación fallida
  13. 13
    DesafíoDistingue un fallo de un error
  14. 14
    ConsejoComprueba qué ha ejecutado realmente la detección de pruebas
  15. 15
    DesafíoUsa un informe para planificar la corrección
  16. 16
    RepasoConserva una prueba del comportamiento que has corregido

Ejercicios de Módulos y depuración en Python

40 Preguntas de Práctica en 4 sets

Set 1: Importaciones, pistas de errores y primeras comprobaciones10 Preguntas de Práctica

Pregunta 1 de 10

Un archivo de programa solo contiene import math antes de su cálculo. ¿Cómo debe llamar a la función de raíz cuadrada con 81?
  1. sqrt(81)
  2. math(81).sqrt()
  3. math.sqrt(81)
  4. import.sqrt(81)
Mostrar respuestaOcultar respuesta
Respuesta: C
La importación crea la vinculación math, así que se accede a la función mediante math.sqrt(81), que devuelve 9.0. Llamar solo a sqrt(81) lanzaría NameError porque esta importación no ha creado una vinculación independiente para sqrt.

Pregunta 2 de 10

Un vehículo de traslado tiene capacidad para 8 personas. ¿Qué devuelve math.ceil(35 / 8) y qué representa?
  1. 5, los vehículos necesarios para todos
  2. 4, los vehículos necesarios para todos
  3. 4.375, los vehículos que debes reservar
  4. 4, la cantidad de asientos que quedan vacíos
Mostrar respuestaOcultar respuesta
Respuesta: A
La división da 4.375, así que cuatro vehículos dejan a tres personas sin asiento. ceil redondea hacia arriba al siguiente entero y da cinco vehículos. Redondear al entero más cercano daría cuatro en este caso, pero se necesitan suficientes vehículos enteros para todos.

Pregunta 3 de 10

Un archivo llamado text_tools.py define shorten. ¿Cómo puede otro archivo de la misma carpeta importarla y llamarla?
  1. import text_tools.py, después text_tools.shorten("Hello")
  2. import shorten, después shorten.text_tools("Hello")
  3. import text_tools, después shorten.text_tools("Hello")
  4. import text_tools, después text_tools.shorten("Hello")
Mostrar respuestaOcultar respuesta
Respuesta: D
El nombre de módulo de un archivo omite la extensión .py, así que import text_tools crea la vinculación con el módulo. La notación de punto permite después acceder a su función shorten. Incluir .py en la importación trata esa terminación como parte de una ruta de importación en lugar de como una extensión de archivo.

Pregunta 4 de 10

Estás en un indicador >>> de Python e introduces pip install cowsay. ¿Por qué informa Python de sintaxis no válida?
  1. El paquete debe importarse antes de poder instalarlo.
  2. El comando de instalación debe ejecutarse en la terminal.
  3. El nombre del paquete debe escribirse con la terminación .py.
  4. El comando de instalación necesita una asignación de Python.
Mostrar respuestaOcultar respuesta
Respuesta: B
El indicador >>> acepta sentencias de Python, mientras que la sintaxis de instalación de pip es un comando de terminal. Sal de la consola de Python y ejecuta python -m pip install cowsay en la terminal. Importar primero no puede hacer que esté disponible un paquete que aún no está instalado.

Pregunta 5 de 10

Una traza termina en ZeroDivisionError. Sus marcos, de arriba abajo, muestran show([]), mean(data) y sum(values) / len(values). ¿Qué cadena explica mejor el fallo?
  1. La función show ha intentado dividir su propio nombre entre cero.
  2. Una lista vacía ha llegado a mean, haciendo que su divisor sea cero.
  3. La lista se ha vaciado porque la traza se muestra en orden inverso.
  4. La suma era cero, lo que siempre hace que una división no sea válida.
Mostrar respuestaOcultar respuesta
Respuesta: B
El marco más reciente divide entre len(values), y las llamadas anteriores permiten seguir ese valor hasta la lista vacía. Su longitud es cero, lo que causa la excepción. Un numerador cero está permitido cuando el divisor no es cero, así que la suma por sí sola no explica este fallo.

Pregunta 6 de 10

¿Qué excepción lanza int("7.25")?
  1. TypeError
  2. NameError
  3. IndexError
  4. ValueError
Mostrar respuestaOcultar respuesta
Respuesta: D
La cadena es un tipo de entrada aceptado por int, pero "7.25" no es texto con la forma de número entero que requiere esta conversión. Eso provoca ValueError. Un TypeError indicaría un tipo de entrada o una operación inadecuados, no este valor de cadena inadecuado.

Pregunta 7 de 10

Una función debería sumar [9, 2, 5] y obtener 16, pero devuelve 7. Sospechas que omite el primer elemento. ¿Qué observación comprobaría esa idea de forma más directa?
  1. Registrar los índices que visita el bucle de suma.
  2. Volver a mostrar el total esperado después de la llamada a función.
  3. Sumar 9 al resultado y comprobar solo esta misma entrada.
  4. Cambiar el nombre de la variable del total y ejecutar sin inspeccionarla.
Mostrar respuestaOcultar respuesta
Respuesta: A
Registrar los índices comprueba la predicción de que nunca se visita el índice 0. Si solo aparecen los índices 1 y 2, eso respalda la hipótesis y señala los límites del bucle. Sumar 9 parchea este resultado, pero no aporta pruebas de que el bucle procese correctamente otras entradas.

Pregunta 8 de 10

¿Qué dos líneas se muestran?

total = 0
for n in [3, 8]:
    print(f"{n=} {total=}")
    total += n
  1. n=3 total=3, después n=8 total=11
  2. n=3 total=0, después n=8 total=0
  3. n=3 total=0, después n=8 total=3
  4. n=0 total=3, después n=3 total=8
Mostrar respuestaOcultar respuesta
Respuesta: C
La llamada a print se ejecuta antes de la suma en cada iteración. Primero muestra el total inicial de 0 y después el total de 3 que ha dejado la primera suma. Mostrar los totales 3 y 11 correspondería a una llamada a print situada después de cada actualización, que no es donde aparece esta llamada.

Pregunta 9 de 10

¿Qué ocurre cuando este código se ejecuta normalmente?

count = 6
assert count < 5, "too many"
print("saved")
  1. Lanza AssertionError con "too many".
  2. Muestra "saved" y después informa de la aserción.
  3. Asigna 5 a count y continúa sin mostrar salida.
  4. Muestra "too many" y después muestra "saved".
Mostrar respuestaOcultar respuesta
Respuesta: A
La condición 6 < 5 es falsa, así que la aserción lanza AssertionError con el mensaje proporcionado. La ejecución se detiene antes de la llamada final a print porque la excepción no se maneja. El mensaje forma parte de la excepción; no es una salida normal tras la que continúa la ejecución.

Pregunta 10 de 10

La regla indica gratuidad hasta un peso de 12 incluido, una tarifa de 4 de 13 a 18 y una tarifa de 7 por encima de 18. Las pruebas con 5 y 20 pasan. ¿Qué resultados y modificación diagnostican correctamente este código?

def fee(weight):
    if weight < 12:
        return 0
    if weight <= 18:
        return 4
    return 7
  1. Para 12: 0; para 18: 7. Cambia la segunda condición a < 18.
  2. Para 12: 4; para 18: 7. Cambia ambas comparaciones a <.
  3. Para 12: 0; para 18: 4. Mantén ambas comparaciones sin cambios.
  4. Para 12: 4; para 18: 4. Cambia la primera condición a <= 12.
Mostrar respuestaOcultar respuesta
Respuesta: D
Para 12, la primera condición es falsa, así que la segunda rama cobra 4 incorrectamente. Para 18, esa segunda rama cobra 4 correctamente. Incluir 12 en la primera rama corrige el límite gratuito; cambiar la segunda comparación crearía otro error en un límite. Las pruebas superadas con valores alejados no comprueban ninguno de los límites.
Set 2: Módulos, decisiones de depuración y resultados de pruebas10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Después de import statistics as st, la siguiente línea es statistics.mean([3, 7]). No hay otras importaciones ni asignaciones. ¿Qué explica el error?
  1. La función mean también requiere import math.
  2. Solo se ha vinculado st; llama a st.mean([3, 7]).
  3. Solo se ha vinculado mean; llama a mean([3, 7]).
  4. El alias debe pasarse como statistics.mean(st).
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

¿Cuál es el valor de tickets después de este código?

import random
tickets = [11, 22, 33]
tickets = random.shuffle(tickets)
  1. Una nueva lista de tres elementos mezclados
  2. El primer elemento de la lista mezclada
  3. La lista original en su orden original
  4. None
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un módulo auxiliar define double y después contiene la línea sin protección print(double(6)). Otro archivo de programa lo importa dos veces en una ejecución. ¿Cuántas veces muestra la salida esa línea?
  1. Una vez, durante la primera importación
  2. Dos veces, una por cada sentencia import
  3. Nunca, porque las importaciones solo leen nombres de funciones
  4. Una vez, solo si el programa llama después a double
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Un editor ejecuta un archivo de programa con Python A. El comando de terminal python -m pip show cowsay indica una ubicación en Python B y el editor no puede importar cowsay. ¿Qué debes hacer primero?
  1. Repetir sin cambios la instalación con el pip de Python B.
  2. Sustituir la importación por la ruta de la carpeta del paquete.
  3. Ejecutar -m pip install cowsay con Python A.
  4. Mover el archivo de programa al directorio de bibliotecas de Python B.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una traza de excepción tiene tres marcos. ¿Dónde encuentras primero el tipo de excepción y el mensaje?
  1. En el primer marco, junto al nombre del archivo de programa
  2. En la cabecera situada encima del primer marco
  3. En la línea con la llamada más antigua
  4. En la última línea, debajo de los marcos
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Esta función debería sumar todas las cantidades. ¿Qué tipo de problema explica el resultado de total([2, 5, 8])?

def total(values):
    result = 0
    for i in range(1, len(values)):
        result += values[i]
    return result
  1. Se produce IndexError porque el bucle llega al índice 3.
  2. Un error lógico hace que devuelva 13 porque se omite el índice 0.
  3. Se produce TypeError porque los elementos de una lista no se pueden sumar.
  4. Se produce un error de sintaxis porque range necesita tres argumentos.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un programa de procesamiento de datos que falla tiene 300 líneas y 200 registros. ¿Qué constituye un ejemplo mínimo reproducible útil?
  1. El código completo con todos los registros y toda la salida de diagnóstico
  2. La respuesta esperada sin ninguna parte de la entrada que falla
  3. El código más breve y la entrada más pequeña que siguen fallando
  4. Un programa reescrito cuya salida ya se ha corregido
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

Una comprobación de entrada usa assert (score >= 0, "negative score"). Se cumple cuando score es -3. ¿Qué cambio corrige la comprobación y mantiene activa la validación con -O?
  1. if score < 0: raise ValueError("negative score")
  2. assert score >= 0, "negative score"
  3. assert (score < 0, "negative score")
  4. assert (score >= 0) == True
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un archivo de pruebas sencillo define test_discount, que contiene dos aserciones, pero nunca la llama. Ejecutas ese archivo con python test_discount.py; no hay código de un ejecutor de pruebas. ¿Por qué no se comprueba ninguna aserción?
  1. Python elimina todas las aserciones de cualquier archivo test_.
  2. Cada aserción debe moverse por encima de la función.
  3. Definir la función no ejecuta su cuerpo.
  4. La función de prueba debe devolver True antes de llamarse.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un método de unittest llama a self.assertEqual(lookup("x"), 7). La llamada a lookup lanza un KeyError inesperado antes de devolver un valor. ¿Qué resultado breve marca esta prueba?
  1. F, porque todo problema en una prueba es un fallo de aserción
  2. E, porque otra excepción ha interrumpido la comprobación
  3. ., porque ninguna comparación de igualdad ha devuelto falso
  4. F, porque KeyError es lo mismo que AssertionError
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 3: Sigue las causas a través de módulos y pruebas10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

¿Qué muestra este código?

from math import sqrt as root
sqrt = 4
result = root(sqrt ** 2)
print(result, sqrt)
  1. 16.0 4
  2. 4.0 4.0
  3. Lanza TypeError porque sqrt es un entero.
  4. 4.0 4
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

Un sorteo usa random.sample(["blue", "blue", "red"], 2). ¿Por qué puede contener el resultado dos valores "blue"?
  1. El muestreo siempre repone el primer elemento antes de volver a extraer.
  2. Las dos entradas azules ocupan posiciones distintas en la entrada.
  3. El valor 2 solicita dos copias idénticas de un elemento elegido.
  4. El muestreo elimina los valores duplicados solo después de devolverlos.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Un módulo contiene este código. Un proceso recién iniciado lo importa y después llama a helper.answer(). ¿Qué ocurre?

# helper.py
if __name__ == "__main__":
    def answer():
        return 42
  1. Devuelve 42 porque Python carga primero todas las definiciones.
  2. NameError: Python nunca define __name__ durante la importación.
  3. AttributeError: la importación ha omitido la definición de la función.
  4. Devuelve None porque la condición de ejecución directa cambia los valores de retorno.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Una traza empieza con tu llamada a run_report(), después muestra tu llamada a parse(raw) y termina dentro de una conversión de biblioteca con ValueError. Inspeccionas raw en tu llamada a parse y encuentras "9x", aunque la regla exige texto que represente un entero. ¿Por dónde debe continuar la investigación?
  1. Seguir dónde ha pasado raw a ser "9x" antes de llamar a parse.
  2. Sustituir int(raw) por int(raw[0]) para que esta entrada produzca un número.
  3. Tomar el marco de biblioteca como prueba de que la biblioteca falla y editar su conversión.
  4. Mantener la entrada y reinstalar la biblioteca porque el código que la llama ya se ha ejecutado.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Una función muestra 18, pero no tiene sentencia return. El código que la llama evalúa después result + 2, donde result es el valor de retorno de la llamada. ¿Por qué se produce TypeError?
  1. result es None, que no se puede sumar a 2.
  2. result es la cadena "18" porque mostrar valores convierte los retornos.
  3. result es 18, pero aquí no es válido sumar dos enteros.
  4. result no está definido porque cada llamada a print elimina su vinculación.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

Una cadena de procesamiento lee, convierte y suma datos. En un fallo reproducible, los valores necesarios para el total ya son incorrectos justo después de la conversión. La lectura por separado produce los valores originales esperados. ¿Cuál es la siguiente investigación más concreta?
  1. Añadir una corrección al total final y dejar la conversión sin cambios.
  2. Reescribir juntas las tres etapas y comparar solo la salida final.
  3. Ejecutar solo la conversión con la entrada original más pequeña que falle.
  4. Inspeccionar solo la salida final porque es donde aparece el resultado incorrecto.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

Un depurador está pausado en answer = calculate(7). Quieres inspeccionar la primera línea dentro de calculate. ¿Qué control debes usar?
  1. Paso a paso por procedimientos
  2. Paso a paso por instrucciones
  3. Salir de la función
  4. Continuar
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

La regla indica que un trayecto es gratuito para distancias de hasta 6 incluidos y cuesta 3 por encima de 6. charge(6) devuelve 3, pero su prueba espera 3 y pasa. ¿Qué cambio crea una prueba de regresión útil y corrige la aplicación de la regla?
  1. Mantener 3 para 6 y añadir solo una prueba de un trayecto largo de pago.
  2. Cambiar la regla para que 6 sea de pago y conservar la prueba existente.
  3. Eliminar la comprobación de 6 y comparar solo dos ejemplos que pasen.
  4. Esperar 0 para 6, ver que falla y después corregir y repetir las pruebas.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un archivo de unittest tiene test_alpha, que espera 4 pero recibe 5, test_beta, que pasa, y test_gamma, que lanza un TypeError inesperado. ¿Qué cadena compacta de progreso produce la ejecución alfabética predeterminada?
  1. E.F
  2. F.E
  3. F.F
  4. .FE
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un unittest.TestCase tiene check_empty, con una comprobación de igualdad que falla, y test_full, con una que pasa. El ejecutor informa de una prueba y OK. ¿Cómo debes hacer que se ejecute la comprobación de comportamiento que falta?
  1. Cambiar el nombre de check_empty a test_empty y volver a ejecutar.
  2. Añadir return False al final de check_empty.
  3. Mover check_empty debajo de test_full en la clase.
  4. Sustituir assertEqual por print en check_empty.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Set 4: Combina decisiones de importación, depuración y pruebas10 Preguntas de Práctica

Guarda esta unidad para ver todas las respuestas y practicar cada set.

Pregunta 1 de 10

Una simulación establece una semilla una vez y después llama a random.randint(2, 5) 50 veces. Una prueba nueva establece la misma semilla con la misma versión de Python y repite las mismas llamadas. ¿Qué deben esperar sus comprobaciones?
  1. La secuencia se repite y todos los resultados están entre 2 y 5 incluidos.
  2. La secuencia se repite y todos los resultados están entre 2 y 4 incluidos.
  3. Cada resultado aparece con igual frecuencia y deben aparecer los cuatro valores.
  4. Cada llamada vuelve a dar el primer resultado porque la semilla sigue establecida.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 2 de 10

La documentación indica beautifulsoup4 como distribución y bs4 como su módulo. Un archivo de programa importa bs4 correctamente. Un compañero quiere cambiar python -m pip install beautifulsoup4 para instalar bs4 y que los nombres coincidan. ¿Es hacer coincidir esos nombres una razón válida para ese cambio?
  1. Sí; toda importación correcta debe usar el nombre de instalación de la distribución.
  2. Sí; importar bs4 demuestra que pip ha instalado una distribución con ese nombre.
  3. No; la instalación usa el nombre de distribución documentado, que puede ser distinto.
  4. No; primero hay que cambiar el nombre del módulo para que coincida con la distribución actual.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 3 de 10

Una nueva ejecución de display.py informa de estas llamadas, de arriba abajo: start(" "), read_count(text) y después int(text), y termina en ValueError. ¿Qué secuencia comprueba mejor la causa probable antes de corregirla?
  1. Inspeccionar solo type(text); recibir una cadena basta para demostrar un error de tipo.
  2. Inspeccionar repr(text), confirmar la entrada en blanco y definir después cómo tratarla.
  3. Mover la misma conversión a start para que se ejecute antes de las otras llamadas a funciones.
  4. Sustituir toda conversión fallida por cero, sin comprobar el comportamiento de entrada requerido.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 4 de 10

Una función de suma omite el primer elemento. Un parche añade 6 a cada total devuelto y ahora pasa la prueba con [6, 3, 2]. ¿Qué resultados esperados y reales para dos entradas nuevas revelan el problema restante?
  1. [9]: esperado 9, real 15; []: esperado 0, real 6.
  2. [9]: esperado 9, real 6; []: esperado 0, real 0.
  3. [9]: esperado 6, real 6; []: esperado 6, real 6.
  4. [9]: esperado 9, real 6; []: esperado 0, real 6.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 5 de 10

Esta función muestra un producto correcto, pero el código que la llama recibe TypeError en area(4, 5) + 1. ¿Dónde debes inspeccionar y qué resultado explica el fallo?

def area(w, h):
    product = w * h
    print(product)
  1. Ejecutar la llamada como un solo paso; su valor devuelto es el entero 20.
  2. Ejecutar la llamada como un solo paso; su valor devuelto es la cadena "20".
  3. Ejecutar la llamada como un solo paso; su valor devuelto es None.
  4. Entrar en la llamada; su resultado mostrado se convierte en el valor de retorno.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 6 de 10

¿Qué ocurre en una ejecución normal, sin optimización?

import math
assert math.isclose(0.1 + 0.2, 0.3)
assert 0.1 + 0.2 == 0.3
  1. La primera aserción se cumple; la segunda lanza AssertionError.
  2. Ambas aserciones se cumplen porque las sumas decimales se almacenan exactamente.
  3. La primera aserción falla; la segunda nunca se ejecuta.
  4. Ambas aserciones fallan, pero el programa continúa hasta el final.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 7 de 10

pick() devuelve un entero aleatorio de 3 a 7, ambos extremos incluidos. pair_total() suma dos llamadas a pick(). Una prueba que exige que cada total sin semilla sea igual a 10 falla a veces, aunque ambas funciones funcionan correctamente. ¿Qué comprobación por resultado coincide con el rango de totales requerido?
  1. Comprobar 3 <= value <= 7 para cada total.
  2. Comprobar 6 <= value < 14 para cada total.
  3. Comprobar value == 10 para cada total.
  4. Comprobar 6 <= value <= 14 para cada total.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 8 de 10

reserve(n) debe aceptar cantidades enteras de 0 a 8 incluidos y lanzar ValueError fuera de ese rango. Las pruebas con assertRaises(ValueError) informan de F para -1 porque no se produce ninguna excepción y de E para 9 porque se produce TypeError. Una prueba con 2 pasa. ¿Qué comportamiento debe proporcionar la corrección?
  1. Aceptar -1 normalmente; lanzar ValueError para 9; mantener 2 válido.
  2. Lanzar ValueError para -1 y 9; mantener 2 válido.
  3. Lanzar ValueError para -1; mantener TypeError para 9; mantener 2 válido.
  4. Aceptar -1 y 9 normalmente; lanzar ValueError para 2.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 9 de 10

Un archivo de programa se llama random.py e importa random, y después falla porque falta random.randint. ¿Qué primer cambio resuelve el conflicto de nombres?
  1. Instalar de nuevo el módulo random con pip.
  2. Mover import random debajo de la llamada a randint.
  3. Mantener random.py y usar from random import randint.
  4. Cambiar el nombre del archivo de programa a draw_numbers.py.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

Pregunta 10 de 10

Un programa tiene assert total == 10 para un cálculo interno y assert age >= 0 para datos del usuario. Se ejecuta con -O, con total igual a 9 y age igual a -1. ¿Qué ocurre con esas comprobaciones y qué cambio mantiene la validación de entrada requerida?
  1. Solo desaparece la comprobación del total; añade un mensaje más largo a la aserción de edad.
  2. Desaparecen ambas comprobaciones; coloca la condición de edad y el mensaje en una tupla.
  3. Desaparecen ambas comprobaciones; usa if age < 0 y una respuesta de error para la entrada.
  4. Solo desaparece la comprobación de edad; muévela a una función llamada test_age.
Mostrar respuestaOcultar respuesta

Guarda esta unidad para ver esta respuesta.

¿Te atascas con una pregunta tuya? Ayuda con Tareas

Términos Clave

60 Términos Clave, cada uno con su definición

A

Alias
Un alias es el nombre elegido con as para un módulo u objeto importado; la importación vincula ese nombre en el programa que importa.
El alias stats de import statistics as stats permite al archivo de programa llamar a stats.mean([1, 3, 8]).
Aserción
Una aserción comprueba una condición que se espera que se cumpla si el código es correcto; continúa cuando es verdadera y lanza AssertionError cuando es falsa.
Una aserción como assert count == 3 comprueba un resultado interno frente a la cantidad que esperas de forma independiente.
AssertionError
Un AssertionError señala una aserción fallida y puede incluir un mensaje proporcionado que explique qué expectativa no ha cumplido la comprobación.
Un AssertionError con "wrong total" dirige la atención hacia la prueba que ha comparado el total calculado.

B

Biblioteca estándar
La biblioteca estándar es la colección de módulos incluidos con Python que proporciona herramientas listas para usar sin instalar un paquete aparte.
La biblioteca estándar incluye math para cálculos y random para simulaciones, como lanzar dados.

C

Cadena de documentación
Una cadena de documentación es una cadena al principio de un módulo o función que documenta su propósito y puede mostrarse mediante help().
Una cadena de documentación de circle_area puede explicar el argumento del radio y el área devuelta al código que la llama.
Cadena de llamadas
Una cadena de llamadas es la secuencia de llamadas a funciones activas que han llevado a la operación actual, desde el código que realiza la llamada externa hasta la llamada más reciente.
Una cadena de llamadas de una función report a una función average muestra cómo una lista ha llegado a la función que divide entre su longitud.
Caso límite
Un caso límite es una entrada de prueba situada en un extremo donde cambia una regla, lo que facilita detectar errores en comparaciones que incluyen o excluyen el límite.
Un caso límite con la puntuación 90 comprueba si la regla de la calificación A usa la comparación requerida que incluye el límite.
Caso límite
Un caso límite es una entrada poco habitual situada en un extremo o límite especial, como una lista vacía, que puede revelar un comportamiento que las entradas habituales no detectan.
Un caso límite con una lista de un elemento puede revelar una función de suma que empieza su bucle en el segundo elemento.
Código de nivel superior
El código de nivel superior está formado por las sentencias del nivel del módulo, fuera de los cuerpos de las funciones, que se ejecutan por orden cuando se carga un módulo por primera vez.
El código de nivel superior que llama a print puede producir salida durante la importación aunque el código que importa no llame a ninguna función.
Condición de ejecución directa
Una condición de ejecución directa es un bloque if __name__ == "__main__": que ejecuta su cuerpo en una ejecución directa y lo omite durante una importación normal.
Una condición de ejecución directa alrededor de main() permite que las pruebas importen las funciones del módulo sin iniciar su aplicación.

D

Depuración
La depuración es el proceso de reproducir un comportamiento inesperado, localizar su causa, corregirla y volver a comprobar el comportamiento afectado.
Depurar un bucle que suma precios incluye observar los índices que visita antes de cambiar el valor inicial del bucle.
Depuración mediante salidas de diagnóstico
La depuración mediante salidas de diagnóstico añade salidas temporales en puntos elegidos del código para revelar valores, el orden de ejecución y si una hipótesis coincide con el comportamiento.
La depuración mediante salidas de diagnóstico con print(f"{i=} {total=}") etiqueta el índice del bucle y el total en el momento inspeccionado.
Depurador
Un depurador pausa la ejecución de un programa y proporciona controles para inspeccionar los valores actuales y avanzar por el código paso a paso.
Un depurador permite entrar en calculate para inspeccionar sus argumentos cuando el código que la llama recibe una respuesta incorrecta.
Detección automática de pruebas
La detección automática de pruebas encuentra pruebas ejecutables mediante reglas de nombres de archivos y métodos, como el patrón de archivos predeterminado test*.py de unittest.
La detección automática de pruebas mediante python -m unittest puede ejecutar los archivos coincidentes sin enumerar cada uno en un comando.
Distribución
Una distribución es un proyecto instalable de Python identificado por un nombre de gestor de paquetes, que puede diferir del nombre usado en las importaciones.
La distribución beautifulsoup4 se instala con ese nombre, pero su documentación indica que se debe importar bs4 en Python.
Divide y vencerás
Divide y vencerás acota una búsqueda de depuración comprobando los valores intermedios necesarios y siguiendo la sección donde empiezan a ser incorrectos.
Divide y vencerás dirige la atención hacia la conversión si los datos originales son correctos, pero los valores convertidos ya son incorrectos.

E

Ejemplo mínimo reproducible
Un ejemplo mínimo reproducible es el código y la entrada más pequeños que conservan un fallo para poder examinar directamente los pasos relevantes.
Un ejemplo mínimo reproducible puede reducir cientos de registros a los dos que siguen desencadenando el mismo fallo.
Error de ejecución
Un error de ejecución es un problema detectado mientras se ejecuta el código, como una operación no válida que lanza una excepción en ese momento.
Se produce un error de ejecución cuando se llega a una expresión de división válida con un divisor cuyo valor es cero.
Error de programación
Un error de programación es una equivocación que hace que el comportamiento de un programa difiera del previsto, incluidas las respuestas incorrectas y los fallos inesperados.
Un error de programación que omite el primer precio puede reproducirse con una lista de un elemento cuyo total esperado sea fácil de comprobar.
Error de prueba
Un error de prueba es un resultado de prueba causado por una excepción inesperada distinta de una aserción fallida, en la prueba o en el código al que llama.
Un error de prueba marcado con E puede producirse cuando una función lanza TypeError antes de que la comprobación de igualdad reciba un valor.
Error de sintaxis
Un error de sintaxis significa que el código incumple la gramática de Python, por ejemplo por la falta de dos puntos, e impide que el archivo de programa afectado se inicie con normalidad.
Un error de sintaxis después de if ready puede corregirse añadiendo los dos puntos necesarios antes de su bloque con sangría.
Error lógico
Un error lógico hace que un programa se comporte incorrectamente aunque sus sentencias se ejecuten sin producir un informe de excepción.
Un error lógico en un bucle que empieza en el índice 1 omite el primer precio y da un total demasiado pequeño.
Especificación
Una especificación establece el comportamiento que debe proporcionar una función y ofrece una base independiente para las entradas, los resultados esperados y las comprobaciones válidas de las pruebas.
La especificación que indica que las puntuaciones de al menos 90 obtienen una A establece la respuesta esperada para una prueba con exactamente 90.
Excepción
Una excepción señala un problema detectado durante la ejecución; una excepción no manejada detiene el programa y normalmente produce una traza de excepción.
Una excepción por división entre cero puede detener average antes de que el código que la llama muestre la media calculada.

F

Fallo de prueba
Un fallo de prueba es un resultado de prueba causado por una aserción falsa, como un valor de retorno real que difiere del valor esperado especificado.
Un fallo de prueba marcado con F puede mostrar que la función ha devuelto "B" donde la regla comprobada exigía "A".

H

Hipótesis
Una hipótesis es una explicación concreta propuesta para un error que predice una observación que puedes comprobar en el programa en ejecución.
La hipótesis de que un bucle omite su primer elemento predice que una salida de sus índices nunca mostrará 0.

I

Importación con comodín
Una importación con comodín usa * para incorporar los nombres públicos de un módulo al programa actual, lo que puede ocultar su origen y sustituir vinculaciones existentes.
La importación con comodín from math import * puede sustituir una variable llamada e por la constante matemática.
ImportError
Un ImportError puede producirse cuando from solicita un nombre que no está disponible en un módulo, aunque Python haya encontrado el propio módulo.
Un ImportError de from math import square_root señala el nombre solicitado, no una instalación ausente.
IndexError
Un IndexError se produce cuando una consulta a una secuencia solicita una posición inexistente, como el índice 3 en una lista de tres elementos.
Un IndexError de names[4] sugiere comprobar la longitud de la lista y los límites del bucle que han producido 4.
Intérprete
Un intérprete es el programa que ejecuta código Python; distintos intérpretes instalados pueden tener disponibles distintos paquetes de terceros.
La elección del intérprete del editor explica por qué un paquete instalado para otro Python puede seguir faltando.

K

KeyError
Un KeyError se produce cuando una consulta a un diccionario solicita una clave ausente, por lo que Python no puede devolver un valor para esa clave mediante indexación.
Un KeyError para "price" puede revelar que el diccionario actual nunca ha recibido la entrada de precio esperada.

M

Marco de ejecución
Un marco de ejecución de una traza identifica la ubicación de una llamada activa mediante su archivo, número de línea y función, junto con la línea de código fuente correspondiente.
El marco más bajo puede mostrar una división entre la longitud de una lista vacía, mientras que los anteriores revelan qué llamador ha proporcionado esa lista.
Método de prueba
Un método de prueba es una función dentro de una clase de pruebas cuyo nombre empieza por test, lo que permite a unittest detectar y ejecutar sus comprobaciones.
Un método de prueba llamado test_limit puede comprobar un límite por separado de la prueba de una entrada habitual.
Módulo
Un módulo es una unidad de código Python, normalmente un archivo .py, cuyas funciones y variables pueden importarse para usarlas en otro programa.
El módulo math proporciona sqrt, de modo que un programa puede calcular raíces cuadradas sin definir esa función.
Muestreo sin reemplazo
El muestreo sin reemplazo elige posiciones distintas de la entrada, de modo que cada posición se selecciona como máximo una vez, aunque los valores se repitan.
El muestreo sin reemplazo de ["A", "A", "B"] puede seleccionar ambas posiciones que contienen "A".

N

NameError
Un NameError se produce cuando Python no encuentra una vinculación para un nombre usado en una expresión, a menudo por un error al escribirlo o por una importación ausente.
Un NameError para sqrt después de usar solo import math significa que la función necesita ahí el prefijo math..
Notación de punto
La notación de punto permite acceder a un atributo con nombre dentro de un objeto o módulo colocando un punto entre el nombre del objeto y el del atributo.
La notación de punto de math.sqrt(25) encuentra la función sqrt dentro del módulo math ya importado.
Número pseudoaleatorio
Un número pseudoaleatorio lo produce un algoritmo determinista cuya secuencia está diseñada para parecer aleatoria en usos como las simulaciones.
Un número pseudoaleatorio de random.randint(1, 6) puede representar el resultado de un dado en la simulación de un juego de mesa.

O

Ocultación de módulos
La ocultación de módulos ocurre cuando un módulo encontrado antes tiene el nombre del módulo que se pretendía usar y lo oculta durante la búsqueda de importación.
La ocultación de módulos causada por un random.py local puede dejar a un programa sin la función randint de la biblioteca.
Opción de optimización
La opción de optimización -O cambia la ejecución de Python al eliminar las sentencias assert, por lo que la validación obligatoria no puede depender de ellas.
Iniciar un archivo de programa con la opción de optimización hace desaparecer una comprobación de edad negativa basada solo en una aserción.
Operación sobre el objeto original (in-place)
Una operación sobre el objeto original modifica un objeto existente, como una lista, en lugar de necesitar un objeto nuevo que contenga los datos modificados.
La operación sobre el objeto original random.shuffle(cards) modifica cards y devuelve None, así que no necesita asignación.

P

Paquete
Un paquete agrupa módulos relacionados de Python, normalmente en una carpeta, para que los programas puedan organizar y reutilizar una colección de código más amplia.
Un paquete de terceros puede proporcionar varios módulos relacionados que un programa importa para distintas tareas.
Parte entera inferior (suelo)
La parte entera inferior de un número es el mayor entero que no supera ese número; math.floor redondea hacia menos infinito cuando es necesario.
La parte entera inferior de -3,2 es -4, por lo que math.floor(-3.2) difiere de la conversión con int(-3.2).
Parte entera superior (techo)
La parte entera superior de un número es el menor entero que no es inferior a ese número; math.ceil realiza este redondeo hacia arriba a un entero.
Un cálculo de la parte entera superior convierte 3,4 latas de pintura necesarias en cuatro latas enteras, suficientes para la superficie indicada.
Paso a paso por instrucciones
El paso a paso por instrucciones es una acción del depurador que entra en una función llamada en la línea actual para que puedas inspeccionar sus pasos internos.
Usa el paso a paso por instrucciones en result = convert(text) cuando el valor devuelto sea incorrecto y el texto de entrada parezca correcto.
Paso a paso por procedimientos
El paso a paso por procedimientos es una acción del depurador que ejecuta la línea actual, incluidas las funciones llamadas, sin seguir sus líneas internas.
Usa el paso a paso por procedimientos en una llamada de cálculo cuando quieras inspeccionar su resultado devuelto en el código que la llama.
pip
pip es una herramienta de instalación que descarga y gestiona distribuciones de Python de terceros para el intérprete que la ejecuta.
Ejecutar python3 -m pip show cowsay pide al pip asociado a python3 que muestre los detalles de instalación de ese paquete.
Prueba unitaria
Una prueba unitaria es una pequeña comprobación automatizada de una unidad, como una función, que compara su comportamiento para una entrada elegida con un resultado esperado.
Una prueba unitaria comprueba que una función de precios devuelva 0 para una lista vacía cuando su especificación exige ese resultado.
Punto de interrupción
Un punto de interrupción marca una ubicación donde un depurador pausa la ejecución, lo que permite inspeccionar antes de continuar con el código siguiente.
Un punto de interrupción antes de una actualización del bucle permite comparar el total actual con el elemento que se va a sumar.
PyPI
PyPI es el Python Package Index, un repositorio público donde se publican distribuciones de terceros disponibles para instalar.
La página de PyPI de un paquete proporciona información y documentación del proyecto que conviene consultar antes de instalarlo.

R

Regresión
Una regresión es un error introducido en un comportamiento que antes funcionaba, a menudo después de modificar código del que dependen otras funciones o pruebas.
Una regresión puede hacer que falle una suma de un solo elemento que antes pasaba, después de un cambio destinado a corregir la entrada vacía.
Ruta de búsqueda de módulos
La ruta de búsqueda de módulos es la lista ordenada de carpetas de sys.path que Python comprueba después de sus módulos integrados al buscar importaciones.
Un archivo auxiliar situado fuera de la ruta de búsqueda de módulos puede producir ModuleNotFoundError cuando el programa lo importa.

S

Semilla
Una semilla inicializa un generador pseudoaleatorio y permite repetir la misma secuencia de llamadas con la misma versión de Python.
Establecer la semilla antes de una simulación permite inspeccionar de nuevo la misma secuencia al depurar.
Suplantación mediante nombres similares
La suplantación mediante nombres similares consiste en publicar con un nombre parecido para engañar a quienes escriben mal el nombre de un proyecto de confianza al instalar software.
Comprobar la escritura exacta del nombre de un proyecto en PyPI ayuda a evitar la suplantación mediante nombres similares al copiar un comando de instalación.

T

Tabla de seguimiento
Una tabla de seguimiento registra los valores de las variables en pasos sucesivos de ejecución, lo que permite seguir un programa a mano e inspeccionar sus cambios.
Una tabla de seguimiento de un bucle de acumulación muestra el total antes y después de sumar cada elemento.
TestCase
Una TestCase es la clase base de unittest para las clases de pruebas; proporciona métodos de aserción y soporte para ejecutar cada prueba detectada.
Una clase que hereda de unittest.TestCase puede llamar a self.assertEqual dentro de sus métodos de prueba con nombre.
Traza de la excepción
Una traza de la excepción informa de la cadena de llamadas activas cuando se produce una excepción no manejada y termina con el tipo de excepción y su mensaje.
Lee primero la última línea de la traza y después sigue el marco que falla hacia arriba hasta la llamada original.
TypeError
Un TypeError señala un tipo inadecuado para una operación o una cantidad incorrecta de argumentos en una llamada a función, como la falta de un argumento obligatorio.
Un TypeError de "Score: " + 8 identifica una cadena y un entero que no pueden unirse mediante esa expresión.

V

Validación de datos de entrada
La validación de datos de entrada comprueba si los datos externos cumplen los requisitos de un programa y responde a las entradas inadecuadas antes de usarlas.
La validación de datos de entrada con if score < 0 sigue activa cuando Python se ejecuta con las aserciones eliminadas.
ValueError
Un ValueError señala que una operación acepta el tipo de la entrada, pero no puede usar su valor concreto, como un texto numérico no válido.
Un ValueError de int("6.2") significa que la cadena no representa un entero con la forma requerida.

Sobre esta unidad

Por StudeliInformar de un error

Crea tus propios Materiales de Estudio

Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.

Comenzar