Tan pronto como empezamos a programar, encontramos para nuestra sorpresa que obtener programas correctos no sería tan sencillo como habíamos pensado. Faltaba por descubrir la depuración. Puedo recordar el instante exacto cuando me di cuenta que una gran parte de mi vida a partir de ese momento sería empleada en encontrar errores en mis propios programas.
- Maurice Wilkes descubre la depuración, 1949
En este punto, si ha estado jugando con los programas, probablemente haya visto que a veces el programa hace cosas que usted no quería que hiciera. Esto es muy común. Depurar es el proceso de descubrir lo que la computadora está haciendo y hacerla que haga lo que usted quiere. Esto puede ser muy difícil. Una vez tardé una semana rastreando un error causado por alguien que puso una xdonde debió haber una y.
Este capítulo será más abstracto que los anteriores. Díganme si es útil.
Lo primero que hay que hacer (parece muy obvio) es aclarar lo que el programa debería hacer si funcionara correctamente. Invente algunos casos de prueba y vea lo que sucede. Por ejemplo, digamos que tengo un programa que calcula el perímetro de un rectángulo (la suma de todos sus lados). Tengo los siguientes casos de prueba:
anchura |
altura | perímetro |
3 | 4 | 14 |
2 | 3 | 10 |
4 | 4 | 16 |
2 | 2 | 8 |
5 | 1 | 12 |
Ahora ejecuto mi programa para todos los casos de prueba y veo si el programa hace lo que espero que haga. Si no lo hace, necesito hallar lo que la computadora esta haciendo.
Por lo común, algunos de los casos de prueba funcionarán bien y otros no. Si este es su caso, trate de descubrir lo que tienen en común los casos que sí funcionan. Por ejemplo, esta es la respuesta de un programa para calcular el perímetro (verá el código en un minuto):
Altura: 3
Anchura: 4
Perimetro = 15
Altura: 2
Anchura: 3
Perimetro = 11
Altura: 4
Anchura: 4
Perimetro = 16
Altura: 2
Anchura: 2
Perimetro = 8
Altura: 5
Anchura: 1
Perimetro = 8
Note que no funcionó para los dos primeros casos, funcionó bien en los siguientes dos y falló en el último. Trate de descubrir lo que tienen en común los casos que funcionaron. Una vez que tenga idea del problema, encontrar la causa será más sencillo. Si fuera necesario, trate más casos de prueba con sus programas.
El siguiente paso es ver el código fuente. Una de las cosas más importantes que uno hace cuando programa es leer código. El modo principal de hacer esto es dar una caminata en el código..
Una caminata en el código empieza en el primer renglón, y sigue hasta que el programa termina. Rizos While y declaraciones if pueden causar que algunos renglones nunca sean ejecutados, mientras que otros sean ejecutados muchas veces. En cada renglón usted descubre lo que Python ha hecho.
Empecemos con el simple programa del perímetro. No lo escriba en el interpretador, vamos a leerlo, no a ejecutarlo. El código fuente es:
altura = input("Altura: ")
anchura = input("Anchura: ")
print "Perimetro = ",anchura+altura+anchura+anchura
Pregunta: ¿Cuál es el primer renglón que Python ejecuta?
Respuesta: El primer renglón es ejecutado primero, siempre.
En este caso, es: altura = input("Altura: ")
Pregunta: ¿Qué hace ese renglón?
Respuesta: Imprime Altura: , espera que el usuario escriba un número y coloca ese valor en la variable altura.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: En general, es el siguiente renglón, en
este caso: anchura = input("Anchura: ")
Pregunta: ¿Qué hace ese renglón?
Respuesta: Imprime Anchura: , espera que el usuario escriba un número y coloca ese número en la variable anchura.
Pregunta: ¿Cuál es el siguiente renglón ejecutado?
Respuesta: Cuando el siguiente renglón carece de sangría,
es el renglón que sigue inmediatamente, así que es: print
"Perimetro = ",
anchura+a
ltura+anchura+anchura
(Es posible ejecutar una función, pero eso le toca a otro capítulo.)
Pregunta: ¿Qué hace ese renglón?
Respuesta: Primero imprime perimetro =, y luego imprime el valor que resulta de anchura+altura+anchura+anchura
Pregunta: ¿anchura+altura+anchura+anchura constituye un cálculo correcto del perímetro?
Respuesta: Veamos, el perímetro de un rectángulo es el fondo (anchura) más el lado izquierdo (altura) más el lado superior (anchura) más el lado derecho (altura) (¿eh?). El último valor debería ser la longitud del lado derecho, lo la altura.
Pregunta: ¿Comprende porqué algunas veces el perímetro fue calculado "correctamente"?
Respuesta: El resultado era correcto cuando la anchura y la altura eran iguales.
El siguiente programa a través del cual caminaremos es un programa que debería imprimir 5 puntos en la pantalla. Sin embargo, esta es la salida del programa:
. . . .
Y este es el programa:
numero = 5
while numero > 1:
print ".",
numero = numero - 1
La caminata en este programa será más complicada, dado que ahora hay porciones con sangría (o estructuras de control). Empecemos:
Pregunta: ¿Cuál es el primer renglón que Python ejecuta?
Respuesta: El primer renglón del archivo: numero = 5
Pregunta: ¿Qué hace ese renglón?
Respuesta: Coloca en número 5 en la variable numero.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: El siguiente renglón es: while numero > 1:
Pregunta: ¿Qué hace ese renglón?
Respuesta: Las declaracions while , en general, evalúan la expresión y si es verdadera ejecutan el bloque de código sangrado, de otro modo saltan el bloque sin ejecutarlo.
Pregunta: ¿Qué hace ahora?
Respuesta: Si numero > 1 es verdadero, los dos siguientes renglones serán ejecutados.
Pregunta: Es numero > 1?
Respuesta: El último valor colocado en numero fue 5y 5 > 1 así que la respuesta es sí.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Dado que el while fue verdadero, el siguiente
renglón es: print ".",
Pregunta: ¿Qué hace ese renglón?
Respuesta: Imprime un punto y como el enunciado termina con una ",", la siguiente impresión será en el mismo renglón de la pantalla.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: numero = numero - 1
ya que es el
siguiente renglón y no hay cambios de sangría.
Pregunta: ¿Qué hace ese renglón?
Respuesta: Calcula numero - 1, el cual es el valor presente de numero (o 5) le resta 1 y coloca el nuevo valor en numero . Básicamente, cambia el valor de numero de 5 a 4.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: El nivel de sangría disminuye, así
que tenemos que ver qué tipo de estructura de control es ésta.
Es un rizo while , así que regresamos a la cláusula
while que dice while numero > 1:
Pregunta: ¿Qué hace ese renglón?
Respuesta: Evalúa numero, resulta igual a 4, y lo
compara con 1. Ya que 4 > 1
el rizo while continúa.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Como el rizo while fue verdadero, el siguiente
renglón es: print ".",
Pregunta: ¿Qué hace ese renglón?
Respuesta: Imprime un segundo punto en el renglón.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: No hay cambio de sangría, así que
es: number = number - 1
Pregunta: ¿Y qué hace ese renglón?
Respuesta: Toma el valor presente de numero (4), le resta 1, lo que resulta en 3 y coloca 3 en numero.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Gracias al cambio de sangría, el siguiente
renglón es: while numero > 1:
Pregunta: ¿Qué hace ese renglón?
Respuesta: Compara el valor presente de numero (3) a 1.
3 > 1
así que el rizo while continúa.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Como lea condición del rizo while fue verdadera,
el siguiente renglón es:print ".",
Pregunta: ¿Y qué hace?
Respuesta: Imprime un tercer punto en el renglón de la pantalla.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Es: numero = numero - 1
Pregunta: ¿Qué hace ese renglón?
Respuesta: Toma el valor presente de numero (3), le resta 1 y hace 2 el nuevo valor de numero.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Regresa al principio del rizo while: while
numero > 1:
Pregunta: ¿Qué hace ese renglón?
Respuesta: Compara el valor presente de numero (2) con 1.
Dado que 2 > 1
el rizo while continúa.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Como el rizo while continúa: print
".",
Pregunta: ¿Qué hace ese renglón?
Respuesta: Descubre el significado de la vida, el universo y todo. Es una broma. (Sólo quería asegurarme de que estuviera poniendo atención.) Imprime un cuarto punto en la pantalla.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: It's: numero = numero - 1
Pregunta: ¿Qué hace ese renglón?
Respuesta: Toma el valor presente de numero (2) le resta 1 y hace 1 el nuevo valor de numero.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Regresa al principio del rizo while: while
numero > 1:
Pregunta: ¿Qué hace ese renglón?
Respuesta: Compara el valor presente de numero (1) con 1.
Como 1 > 1
es falso (uno no es mayor que uno), el rizo while
termina.
Pregunta: ¿Cuál es el siguiente renglón?
Respuesta: Ya que la condición del rizo look fue falsa,
el siguiente renglón el aquél después de que el rizo
sale, o: print
Pregunta: ¿Qué hace ese renglón?
Respuesta: Hace que la pantalla vaya al siguiente renglón.
Pregunta: ¿Porqué el programa no imprime 5 puntos?
Respuesta: El rizo sale antes del último punto.
Pregunta: ¿Cómo podemos arreglar eso?
Respuesta: Hacemos que el rizo salga después de imprimir un punto más.
Pregunta: Y cómo hacemos eso?
Respuesta: Hay varios modos. Uno sería cambiar la
condición del rizo while a:while numero > 0:
Otro
modo sería cambiar el enunciado condicional a: numero >= 1
Existen otros modos más.
Necesita descubrir lo que el programa está haciendo. Necesita definir lo que el programa debería hacer. Encuentre cuál es la diferencia entre los dos. Depurar es una habilidad aprendida con la práctica. Si no puede descubrir el problema después de aproximadamente una hora, tómese un descanso, hable con alguien acerca del problema y piense en la imortalidad del cangrejo. Regrese después de un rato y probablemente tendrá nuevas ideas acerca del problema. Buena suerte.