Herramientas Informaticas

Categoría: Pensar como programador Página 1 de 5

1.3.1. Errores sintácticos

Python solo puede ejecutar un programa si el programa es correcto sintácticamente. En caso contrario, es decir si el programa no es correcto sintácticamente, el proceso falla y devuelve un mensaje de error. El término sintaxis se refiere a la estructura de cualquier programa y a las reglas de esa estructura. Por ejemplo, en español la primera letra de toda oración debe ser mayúscula, y todas las oraciones deben terminar con un punto. esta oración tiene un error sintáctico.

Esta oración también para la mayoría de lectores, unos pocos errores sintácticos no son significativos, y por eso pueden leer la poesía de e. e. cummings sin anunciar errores de sintaxis. Python no es tan permisivo. Si hay aunque sea un solo error sintáctico en el programa, Python mostrará un mensaje de error y abortará la ejecución del programa. Durante las primeras semanas de su carrera como programador pasará, seguramente, mucho tiempo buscando errores sintácticos. Sin embargo, tal como adquiera experiencia tendrá menos errores y los encontrará mas rápido.

1.3.3. Errores semánticos

El tercer tipo de error es el error semántico. Si hay un error de lógica en su programa, el programa se ejecutará sin ningún mensaje de error, pero el resultado no será el deseado. Será cualquier otra cosa. Concretamente, el programa hará lo que usted le dijo.

A veces ocurre que el programa escrito no es el programa que se tenía en mente.

El sentido o significado del programa (su semántica) no es correcto. Es difícil hallar errores de lógica, porque requiere trabajar al revés, observando el resultado del programa para averiguar lo que hace.

1.3.4. Depuración experimental

Una de las técnicas mas importantes que usted aprendería es la depuración. Aunque a veces es frustrante, la depuración es una de las partes mías intelectualmentericas, interesantes y estimulantes de la programación.

La depuración es una actividad parecida a la tarea de un investigador: se tienen que estudiar las claves para inducir los procesos y eventos llevaron a los
resultados que tiene a la vista.

La depuración también es una ciencia experimental. Una vez que se tiene la idea de cual es el error, se modifica el programa y se intenta nuevamente. Si su hipótesis fue la correcta se pueden predecir los resultados de la modificación y estaría mías cerca de un programa correcto. Si su hipótesis fue errónea tendría que idearse otra hipótesis. Como dijo Sherlock Holmes, “Cuando se ha descartado lo imposible, lo que queda, no importa cuan inverosímil, debe ser la verdad.”(A. Conan Doyle, The Sign of Four)

Para algunas personas, la programación y la depuración son lo mismo: la programación es el proceso de depurar un programa gradualmente hasta que haga lo que usted quiera. La idea es que deberí³a usted comenzar con un programa que haga algo y hacer pequeñas modificaciones, depurándolas sobre la marcha, de modo que siempre tenga un programa que funcione.

Por ejemplo, Linux es un sistema operativo que contiene miles de lí³neas de código, pero Linus Torvalds lo comenzó como un programa para explorar el microprocesador Intel 80836. Según Larry Greenfield, “Uno de los proyectos tempranos de Linus fue un programa que alternaba la impresión de AAAA con BBBB. Este programa evolucionó en Linux” (de The Linux Users’Guide Versión Beta 1).
Otros capítulos tratarían mas acerca del tema de depuración y otras técnicas de programación.

1.3.2. Errores en tiempo de ejecución

El segundo tipo de error es un error en tiempo de ejecución. Este error no aparece hasta que se ejecuta el programa. Estos errores también se llaman excepciones

porque indican que algo excepcional (y malo) ha ocurrido.

Con los programas que vamos a escribir al principio, los errores en tiempo de ejecución ocurrirán con poca frecuencia, así que puede pasar bastante tiempo hasta que vea uno.

1.4. Lenguajes formales y lenguajes naturales

Los lenguajes naturales son los lenguajes hablados por seres humanos, como el español, el inglés y el francés. No los han diseñados personas (aunque se
intente poner cierto orden en ellos), sino que se han desarrollado naturalmente.

Los lenguajes formales son lenguajes diseñados por humanos y que tienen aplicaciones específicas. La notación matemática, por ejemplo, es un lenguaje formal ya que se presta a la representación de las relaciones entre números y símbolos. Los químicos utilizan un lenguaje formal para representar la estructura química de las moléculas. Y lo más importante:

Los lenguajes de programación son lenguajes formales desarrollados para expresar computaciones.

Los lenguajes formales casi siempre tienen reglas sintácticas estrictas. Por ejemplo, 3+3 = 6 es una expresión matemática correcta, pero 3 = +6$ no lo es. De
la misma manera, H20 es una nomenclatura química correcta, pero 2Zz no lo es.

Existen dos clases de reglas sintácticas, en cuanto a unidades y estructura. Las unidades son los elementos básicos de un lenguaje, como lo son las palabras, los números y los elementos químicos. Por ejemplo, en 3=+6$, $ no es una unidad matemática aceptada (al menos hasta donde nosotros sabemos. Similarmente, 2Zz no es formal porque no hay ningún elemento con la abreviatura Zz.

La segunda clase de regla sintáctica está relacionada con la estructura de un elemento; o sea, el orden de las unidades. La estructura de la sentencia 3=+6$
no se acepta porque no se puede escribir el símbolo de igualdad seguido de un símbolo positivo. Similarmente, las fórmulas moleculares tienen que mostrar el número de subíndice después del elemento, no antes.

A manera de práctica, trate de producir una oración con estructura aceptada pero que esté compuesta de unidades irreconocibles. Luego escriba otra oración con unidades aceptables pero con estructura no válida.

Al leer una oración, sea en un lenguaje natural o una sentencia en un lenguaje técnico, se debe discernir la estructura de la oración. En un lenguaje natural este proceso, llamado análisis sintáctico ocurre subconscientemente.

Por ejemplo cuando usted escucha la oración “El otro zapato cayó”, entiende que “el otro zapato” es el sujeto y “cayó” es el verbo. Cuando se ha analizado la oración sintácticamente, se puede deducir el significado, o la semántica, de la oración. Suponiendo que sepa lo que es un zapato y lo que es caer, entenderá el significado de la oración.

Aunque existen muchas cosas en común entre los lenguajes naturales y los lenguajes formales|por ejemplo las unidades, la estructura, la sintaxis y la
semántica|también existen muchas diferencias:

ambigüedad: Los lenguajes naturales tienen muchísimas ambigüedades, que los hablantes sortean usando claves contextuales y otra información. Los lenguajes formales se diseñan para estar completamente libres de am-

redundancia: Para reducir la ambigüedad y los malentendidos, las lenguas naturales utilizan bastante redundancia. Como resultado suelen ser prolijos. Los lenguajes formales son menos redundantes y más concisos.

literalidad: Los lenguajes naturales tienen muchas metáforas y frases hechas.
programas: El significado de un dicho, por ejemplo “Estirar la pata”, es diferente al significado de sus sustantivos y verbos. En este ejemplo, la oración no tiene nada que ver con un pie y significa ‘morirse’. Los lenguajes formales no difieren de su significado literal.

Los que aprenden a hablar un lenguaje natural|es decir, todo el mundo| muchas veces tienen dificultad en adaptarse a los lenguajes formales. A veces
a diferencia entre los lenguajes formales y los naturales es comparable a la diferencia entre la prosa y la poesía:

Poesía: Se utiliza una palabra por su cualidad auditiva tanto como por su significado. El poema, en su totalidad, produce un efecto o reacción emocional.
La ambigüedad no es solo común sino utilizada a propósito.

Prosa: El significado literal de la palabra es mas importante y la estructura da más significado aún. La prosa se presta al análisis más que la poesía, pero todavía contiene ambigüedad.

Programas: El significado de un programa es inequívoco y literal, y es entendido en su totalidad analizando las unidades y la estructura.
He aquí unas sugerencias para la lectura de un programa (y de otros lenguajes formales). Primero, recuerde que los lenguajes formales son mucho más densos que los lenguajes naturales, y por consecuente lleva más tiempo leerlos. También, la estructura es muy importante, así que entonces no es una buena idea leerlo de pies a cabeza, de izquierda a derecha. En vez de eso, aprenda a separar las diferentes partes en su mente, identificar las unidades e interpretar la estructura. Finalmente, ponga atención a los detalles. Los fallos de puntuación y la ortografía, que puede obviar en el lenguaje natural, pueden suponer una gran diferencia en un lenguaje formal.

1.5. El primer programa

Tradicionalmente el primer programa en un lenguaje nuevo se llama “Hola, mundo” (Hello world!) porque sólo muestra las palabras “Hola a todo el mundo”.

En Python es así:

   1: print "Hola, mundo"

 

Este es un ejemplo de una sentencia print, la cual no imprime nada en papel, más bien muestra un valor. En este caso, el resultado es las palabras Hola, mundo

Las comillas señalan el comienzo y el final del valor; no aparecen en el resultado.

Alguna gente evalúa la calidad de un lenguaje de programación por la simplicidad del programa “Hola, mundo”. Si seguimos ese criterio, Python cumple con todas sus metas.

1.6. Glosario

solución de problemas: El proceso de formular un problema, hallar la solución y expresar esa solución.

lenguaje de alto nivel: Un lenguaje como Python diseñado para ser fácil de leer y escribir para la gente.

lenguaje de bajo nivel: Un lenguaje de programación diseñado para ser fácil de ejecutar para un computador; también se lo llama lenguaje de máquina “o lenguaje ensamblador”.

portabilidad: La cualidad de un programa que le permite ser ejecutado en más de un tipo de computador.

interpretar: Ejecutar un programa escrito en un lenguaje de alto nivel traduciéndolo línea por línea

compilar: Traducir un programa escrito en un lenguaje de alto nivel a un lenguaje de bajo nivel todo al mismo tiempo, en preparación para la ejecución
posterior.

código fuente: Un programa escrito en un lenguaje de alto nivel antes de ser compilado.

código de objeto: La salida del compilador una vez que ha traducido el programa.

programa ejecutable: Otro nombre para el código de objeto que está listo para ejecutarse.

guión: Un programa archivado (que va a ser interpretado).

programa: Un conjunto de instrucciones que especifica una computación.

algoritmo: Un proceso general para resolver una clase completa de problemas.

error (bug): Un error en un programa.

depuración: El proceso de hallazgo y eliminación de los tres tipos de errores de programación.

sintaxis: La estructura de un programa.

error sintáctico: Un error en un programa que hace que el programa sea imposible de analizar sintácticamente (e imposible de interpretar).

error en tiempo de ejecución: Un error que no ocurre hasta que el programa ha comenzado a ejecutarse e impide que el programa continúe.

excepción: Otro nombre para un error en tiempo de ejecución.

error semántico: Un error en un programa que hace que ejecute algo que no era lo deseado.

semántica: El significado de un programa.

lenguaje natural: Cualquier lenguaje hablado que evolucionó de forma natural.

lenguaje formal: Cualquier lenguaje diseñado por humanos que tiene un propósito específico, como la representación de ideas matemáticas o programas de computadores; todos los lenguajes de programación son lenguajes formales.

unidad: Uno de los elementos básicos de la estructura sintáctica de un programa, análogo a una palabra en un lenguaje natural.

análisis sintáctico: La examinación de un programa y el análisis de su estructura sintáctica.

sentencia print: Una instrucción que causa que el interprete Python muestre un valor en el monitor.

5.7. Un ejemplo más

En el ejemplo anterior, usamos variables temporales para ir apuntando los resultados y para hacer que el código fuese mas fácil de depurar, pero podríamos habernos ahorrado unas cuantas l³neas:

   1: def factorial(n):

   2:     if n == 0:

   3:         return 1

   4:     else:

   5:         return n * factorial(n-1)

De ahora en adelante, tenderemos a usar la version mas concisa, pero le recomendamos que utilice la version mas explícita mientras se halle desarrollando código. Cuando lo tenga funcionando, lo podra acortar, si se siente inspirado.

Después de factorial, el ejemplo mas comun de una funcion matematica recursivamente de¯nida es fibonacci, que presenta la siguiente definición:
fibonacci(0) = 1
fibonacci(1) = 1
fibonacci(n) = fibonacci(n ¡ 1) + fibonacci(n ¡ 2);
Traducido a Python, es como sigue:

   1: def fibonacci (n):

   2:     if n == 0 or n == 1:

   3:         return 1

   4:     else:

   5:         return 

   6:         fibonacci(n-1) + fibonacci(n-2)

   7:     

Si intenta seguir el flujo de ejecución aquí, incluso para valores relativamente pequeños de n, le puede dar un dolor de cabeza. Pero si confiamos en el acto de fe, si da por supuesto que las dos llamadas recursivas funcionan correctamente, entonces estara claro que obtiene el resultado correcto al sumarlas juntas.

5.8. Comprobación de tipos

¿Que sucede si llamamos a factorial y le damos 1.5 como argumento?

   1: >>> factorial (1.5)

   2: RuntimeError: Maximum recursion depth 

   3: exceeded

Tiene todo el aspecto de una recursion infinita. Pero, ¿como ha podido ocurrir?

Hay una condicion de salida o caso base: cuando n == 0. El problema es que el valor de n yerra el caso base.
En la primera llamada recursiva, el valor de n es 0.5. En la siguiente vez su valor es -0.5. A partir de ahí, se vuelve mas y mas peque~no, pero nunca sera 0.

Tenemos dos opciones. Podemos intentar generalizar la funcion factorial para que trabaje con numeros de coma flotante, o podemos hacer que factorial compruebe el tipo de su parametro. La primera opcion se llama funcion gamma, y esta mas alla del objetivo de este libro. Así pues, tomemos la segunda.

Podemos usar la funcion type para comparar el tipo del parametro con el tipo de un valor entero conocido (por ejemplo 1). Ya que estamos en ello, podemos asegurarnos de que el parametro sea positivo:

   1: def factorial (n):

   2:     if type(n) != type(1):

   3:         print "El factorial esta 

   4:         definido solo para enteros."

   5:         return -1

   6:     elif n < 0:

   7:         print "El 

   8:         factorial esta definido solo para enteros

   9:         positivos."

  10:         return -1

  11:     elif n == 0:

  12:         return 1

  13:         else:

  14:         return n * factorial(n-1)

  15:     

Ahora tenemos tres condiciones de salida o casos base. El primero filtra los números no enteros. El segundo evita los enteros negativos. En ambos casos, se muestra un mensaje de error y se devuelve un valor especial, -1, para indicar a quien hizo la llamada a la funcion que algo fue mal:

   1: >>> factorial (1.5)

   2: El factorial esta definido solo para 

   3: enteros.

   4: -1

   5: >>> factorial (-2)

   6: El factorial esta definido solo 

   7: para enteros positivos.

   8: -1

   9: >>> factorial ("paco")

  10: El factorial 

  11: esta definido solo para enteros.

  12: -1

Si pasamos ambas comprobaciones, entonces sabemos que n es un entero positivo y podemos probar que la recursion termina.

Este programa muestra un patron que se llama a veces guardian. Las primeras dos condicionales actuan como guardianes, protegiendo al código que sigue de los valores que pudieran causar errores. Los guardianes hacen posible demostrar la correccion del código.

5.9. Glosario

función productiva: Función que devuelve un valor de retorno.

valor de retorno: El valor obtenido como resultado de una llamada a una función.

variable temporal: Variable utilizada para almacenar un valor intermedio en un calculo complejo.

código muerto: Parte de un programa que no podrá ejecutarse nunca, a menudo debido a que aparece tras una sentencia de return.

None: Valor especial de Python que devuelven funciones que o bien no tienen sentencia de return o bien tienen una sentencia de return sin argumento.

desarrollo incremental: Un metodo de desarrollo de programas que busca evitar el depurado añadiendo y probando una pequeña cantidad de código en cada paso.

andamiaje: El código que se usa durante el desarrollo del programa pero que no es parte de la versión final.

Página 1 de 5

Creado con WordPress & Tema de Anders Norén