Revisión automática de la práctica 04-formas
Este es el resultado de una revisión automática de la prácica 04-formas, tal y como la hemos recogido de este repositorio de entrega. Por favor, ten en cuenta que al ser una revisión automática, realizada en parte con la ayuda de un asistente de inteligencia artificial generativa, puede incluir errores, y ser incorrecta. Pero leela con atención, porque creemos que puede tener información útil. Si tienes cualquier duda, o crees que la revisión es errónea, por favor, consulta con los profesores de la asignatura.
- Comprobación de archivos con extension '.py'
- Comprobación con ficheros de solución
- Prueba automática del programa
- Revisión automática de programa
- Análisis
- Recomendaciones de mejora
Comprobación de archivos con extension '.py'
- Archivos Python excluidos de la búsqueda: pixels.py
- Archivos Python encontrados (excluyendo esos): formas.py
Correcto, se elige formas.py como entrega.
Comprobación con ficheros de solución
Los archivos son diferentes de los de la solución.
Prueba automática del programa
Pruebas realizadas por 04-formas/tests/test_argumentos.py:
***ERROR:***
Error ejecutando los tests: Command '['python3', '-m', 'unittest', 'test_argumentos.py']' timed out after 30 seconds
Pruebas realizadas por 04-formas/tests/test_formas.py:
***ERROR:***
Error ejecutando los tests: Command '['python3', '-m', 'unittest', 'test_formas.py']' timed out after 30 seconds
Pruebas realizadas por 04-formas/tests/test_funciones.py:
***ERROR:***
Error ejecutando los tests: Command '['python3', '-m', 'unittest', 'test_funciones.py']' timed out after 30 seconds
Revisión automática de programa
Programa revisado:
import sys
import pixels
from pixels import tam_lienzo, pinta, espera
def lee_formas():
"""Lee los argumentos de línea de comandos y construye una lista de
diccionarios que representan las formas."""
COLORES_VALIDOS = {'red', 'green', 'blue', 'yellow', 'orange', 'purple', 'black', 'white'}
argumentos = sys.argv[1:]
formas = []
while len(argumentos) > 0:
forma = argumentos[0]
try:
if forma == "cuad":
if len(argumentos) < 4:
print(f"Error cuad: El numero de argumentos es incorrecto. Por favor, introduce (x,y,lado)")
break
coord_cuadx = int(argumentos[1])
coord_cuady = int(argumentos[2])
lado_c = int(argumentos[3])
color_cuad = "black"
args_a_consumir = 4
if len(argumentos) > 4:
if argumentos[4] in COLORES_VALIDOS:
color_cuad = argumentos[4]
args_a_consumir = 5
print(f"Forma detectada: Cuadrado en {coord_cuadx} x {coord_cuady}, lado {lado_c}, color {color_cuad}")
formas.append({'tipo': 'cuad', 'x': coord_cuadx, 'y': coord_cuady, 'lado': lado_c, 'color': color_cuad})
argumentos = argumentos[args_a_consumir:]
elif forma == "rect":
if len(argumentos) < 5:
print("Error rect: El numero de argumentos es incorrecto. Por favor, introduce (x,y,ancho,alto)")
break
coord_rectx = int(argumentos[1])
coord_recty = int(argumentos[2])
ancho_r = int(argumentos[3])
alto_r = int(argumentos[4])
color_rect = "black"
args_a_consumir = 5
if len(argumentos) > 5:
if argumentos[5] in COLORES_VALIDOS:
color_rect = argumentos[5]
args_a_consumir = 6
print(
f"Forma detectada: Rectangulo en {coord_rectx} x {coord_recty}, {ancho_r}x{alto_r}, color {color_rect}")
formas.append({'tipo': 'rect', 'x': coord_rectx, 'y': coord_recty, 'ancho': ancho_r, 'alto': alto_r,
'color': color_rect})
argumentos = argumentos[args_a_consumir:]
else:
print(f"Forma: {forma} desconocida. Solo puedo dibujar usando cuad y rect")
break
except ValueError:
print(f"Error: Las coordenadas y dimensiones para '{forma}' tienen que ser un numero entero.")
break
except IndexError:
print("Error: Faltan argumentos.")
break
...
return formas
def dibuja_cuadrado(x_ini, y_ini, lado, color="black"):
for dx in range(lado):
# Bucle 'dy' (delta y) de 0 a 'lado'
for dy in range(lado):
# Coordenada final del píxel
px = x_ini + dx
py = y_ini + dy
# Comprobar si el píxel (px, py) está dentro de los límites del lienzo
if 0 <= px < pixels.ancho and 0 <= py < pixels.alto:
pinta(px, py, color)
"""Dibuja un cuadrado en el lienzo."""
...
def dibuja_rectangulo(x_ini, y_ini, ancho, alto, color="black"):
for dx in range(ancho):
# Bucle 'dy' (delta y) de 0 a 'alto'
for dy in range(alto):
# Coordenada final del píxel
px = x_ini + dx
py = y_ini + dy
# Comprobar si el píxel (px, py) está dentro de los límites del lienzo
if 0 <= px < pixels.ancho and 0 <= py < pixels.alto:
pinta(px, py, color)
"""Dibuja un rectángulo en el lienzo."""
...
def main():
"""Programa principal"""
tam_lienzo()
formas = lee_formas()
for forma in formas:
tipo = forma["tipo"]
x = forma["x"]
y = forma["y"]
color = forma.get("color", "black") # .get() es una buena forma de obtener el color o "black"
# --- CORRECCIÓN ---
# Debe coincidir con lo que guarda lee_formas ('cuad', no 'cuadrado')
if tipo == "cuad":
lado = forma["lado"]
dibuja_cuadrado(x, y, lado, color)
# --- CORRECCIÓN ---
# Debe coincidir con lo que guarda lee_formas ('rect', no 'rectángulo')
elif tipo == "rect":
ancho_forma = forma["ancho"]
alto_forma = forma["alto"]
dibuja_rectangulo(x, y, ancho_forma, alto_forma, color)
# Llama a espera() al final para mantener la ventana abierta
espera()
if __name__ == "__main__":
main()
Análisis
Cumple con el enunciado
El programa no cumple completamente con el enunciado.
- Las funciones
dibuja_cuadrado()ydibuja_rectangulo()no devuelvenTrueoFalsecomo exige el enunciado, a pesar de que su documentación lo menciona. Actualmente no tienen sentenciasreturn, por lo que devuelvenNoneimplícitamente. - En
lee_formas(), al detectar un error (ej.: argumentos insuficientes o valores no enteros), detiene el procesamiento conbreak, ignorando las formas válidas que puedan venir después. El enunciado requiere devolver solo las formas válidas, no abortar ante el primer error. - Aunque el dibujo de píxeles se realiza correctamente dentro de los límites del lienzo, no se verifica si la figura completa cabe en el lienzo antes de dibujar (como exige el enunciado para devolver
Falsesi "se sale del lienzo"). Actualmente pinta solo los píxeles que entran, pero no rechaza la figura completa si parte de ella está fuera.
Es fácil de leer y entender
El código es mayormente comprensible para un principiante:
- Los nombres de variables son descriptivos (ej.:
coord_cuadx,lado_c). - Los comentarios explican el propósito de los bucles y condiciones.
- La estructura de
lee_formas()sigue un flujo lógico al procesar cada forma.
Sin embargo, la falta de manejo de errores robusto (como continuar tras un error) y la ausencia dereturnen las funciones de dibujo pueden generar confusión sobre el comportamiento esperado.
Sigue buenas prácticas de programación
Presenta algunas buenas prácticas, pero con fallos críticos:
-
✅ Uso de constantes para colores válidos (COLORES_VALIDOS), evitando "números mágicos". -
✅ Validación de tipos (contry/exceptparaValueError). -
❌ No maneja errores de forma resiliente: al encontrar un argumento inválido, detiene todo el procesamiento en lugar de omitir solo esa forma. -
❌ Falta coherencia con el enunciado: las funciones de dibujo no implementan el retorno deTrue/Falseni la verificación de límites completa requerida. -
❌ Los bucles de dibujo verifican píxeles individuales, pero no evalúan si la figura completa cabe en el lienzo, lo que contradice el requisito de devolverFalsesi "se sale".
Recomendaciones de mejora
-
En
lee_formas():- Reemplaza
breakporcontinueal detectar errores, para omitir solo la forma inválida y seguir procesando las siguientes. Por ejemplo:if len(argumentos) < 4: print("Error cuad: Faltan argumentos. Se omite esta figura.") argumentos = argumentos[1:] # Avanza al siguiente argumento continue
- Reemplaza
-
En
dibuja_cuadrado()ydibuja_rectangulo():-
Verifica primero si la figura cabe completa en el lienzo:
if x_ini + lado > pixels.ancho or y_ini + lado > pixels.alto: return False # Fuera de límites -
Devuelve
Truetras dibujar (solo si toda la figura cabe):for dx in range(lado): for dy in range(lado): pinta(x_ini + dx, y_ini + dy, color) return True
-
Verifica primero si la figura cabe completa en el lienzo:
-
Simplifica la validación de colores:
- El enunciado no exige restringir colores a una lista específica. Si
pixels.pymaneja colores inválidos, eliminaCOLORES_VALIDOSy usa el color directamente (con valor por defecto"black").
- El enunciado no exige restringir colores a una lista específica. Si
-
Evita código redundante:
- En
lee_formas(), elimina losprintde depuración como"Forma detectada:..."si no son requeridos por el enunciado.
- En