El objetivo de este libro es enseñarle a pensar como lo hacen los científicos informáticos. Esta manera de pensar combina algunas de las mejores características de la matemática, la ingeniería y las ciencias naturales. Como los matemáticos, los científicos informáticos usan lenguajes formales para denotar ideas (específicamente, cómputos). Como los ingenieros, ellos diseñan cosas, construyendo sistemas mediante el ensamble de componentes y evaluando las ventajas y desventajas de cada una de las alternativas de construcción. Como los científicos, ellos observan el comportamiento de sistemas complejos, forman hipótesis, y prueban sus predicciones.
La habilidad más importante del científico informático es la resolución de problemas. La resolución de problemas incluye poder formular problemas, pensar en soluciones de manera creativa, y expresar soluciones claras y precisas. Como se verá, el proceso de aprender a programar es la oportunidad perfecta para desarrollar la habilidad de resolver problemas. Por esa razón este capítulo se llama “El Camino del programa.”
A cierto nivel, usted aprenderá a programar, lo cual es una habilidad muy útil por sí misma. A otro nivel, usted utilizará la programación para obtener algún resultado. Ese resultado se verá más claramente durante el proceso.
El lenguaje de programación que aprenderá es Python. Python es un ejemplo de lenguaje de alto nivel; otros lenguajes de alto nivel de los que quizá ha oído hablar son C++, PHP y Java.
Como se puede deducir, además de “lenguajes de alto nivel” también existen lenguajes de bajo nivel, que también se denominan “lenguajes de máquina” o “lenguajes ensambladores.” A propósito, las computadoras sólo ejecutan programas escritos en lenguajes de bajo nivel. Así, los programas escritos en lenguajes de alto nivel tienen que ser traducidos antes de ser ejecutados. Esta traducción lleva tiempo, lo que es una pequeña desventaja de los lenguajes de alto nivel.
Aun así, las ventajas son enormes. En primer lugar, la programación en lenguajes de alto nivel es mucho más fácil; escribir programas en un lenguaje de alto nivel toma menos tiempo, los programas son más cortos y más fáciles de leer, y es más probable que estos programas queden correctos. En segundo lugar, los lenguajes de alto nivel son portables, lo que significa que los programas escritos con estos lenguajes pueden ser ejecutados en diferentes tipos de computadoras sin modificación alguna o con pocas modificaciones. Los programas escritos en lenguajes de bajo nivel sólo pueden ser ejecutados en un tipo de computadora y deben ser reescritos para ser ejecutados en otra.
Debido a estas ventajas, casi todo programa se escribe en un lenguaje de alto nivel. Los lenguajes de bajo nivel son sólo usados para unas pocas aplicaciones especiales.
Hay dos tipos de programas que traducen lenguajes de alto nivel a lenguajes de bajo nivel: intérpretes y compiladores. Un intérprete lee un programa de alto nivel y lo ejecuta, lo que significa que lleva a cabo lo que indica el programa. Es decir, traduce el programa poco a poco, leyendo y ejecutando cada comando.
Un compilador lee el programa y lo traduce completo antes de su ejecución. En este caso, al programa de alto nivel se le llama código fuente, y el programa traducido es llamado código objeto o programa ejecutable. Una vez que un programa ha sido compilado, puede ser ejecutado repetidamente sin necesidad de más traducción.
Muchos de los lenguajes modernos usan ambos tipos de programas de traducción. Estos lenguajes se traducen primero a un lenguaje de bajo nivel, llamado código de bytes, y después son interpretados por un programa denominado máquina virtual. Aunque Python usa ambos tipos de programas de traducción, usualmente se le considera un lenguaje interpretado debido a la manera en que los programadores interactúan con él.
Existen dos maneras de usar el intérprete de Python: en modo de comandos y en modo de guión. En modo de comandos se escriben sentencias en lenguaje Python en el intérprete de comandos de Python y éste muestra el resultado inmediatamente:
$ python
Python 2.5.1 (r251:54863, May 2 2007, 16:56:35)
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print 1 + 1
2
La primera línea de este ejemplo es el comando que pone en marcha al intérprete de Python — en el indicador de comandos de sistemas tipo UNIX. Las tres líneas siguientes son mensajes del intérprete. La quinta línea comienza con >>>, que es el indicador del intérprete de comandos de Python para indicar que está listo. Si escribimos print 1 + 1 el intérprete contestará 2.
Alternativamente, se puede escribir el programa en un archivo y usar el intérprete para ejecutar el contenido de dicho archivo. El archivo, en este caso, se denomina archivo guión. Por ejemplo, en un editor de texto se puede crear un archivo con el nombre primerprograma.py que contenga lo siguiente:
print 1 + 1
Por convención, los archivos que contienen programas de Python tienen nombres que terminan con .py.
Para ejecutar el programa, se le tiene que indicar al intérprete el nombre del guión:
$ python primerprograma.py
2
Estos ejemplos muestran a Python corriendo desde la línea de comandos de sistemas tipo Unix. En otros entornos de desarrollo los detalles de la ejecución de programas diferirán. También, la mayoría de los programas son más interesantes que el mencionado.
En los ejemplos de este libro se usa tanto el intérprete de Python como los guiones. Usted será capaz de identificar cualquiera de ellos, puesto que los ejemplos en modo de comandos siempre empezarán con el indicador del intérprete de comandos de Pyhton (>>>).
En la realización de pruebas de segmentos cortos de código programado en Python, es más conveniente trabajar en el modo de comandos porque se obtienen resultados inmediatos. Piense en esto como un borrador que se utiliza para ayudarle a resolver problemas. Cualquier segmento de código más allá de unas pocas líneas debe incluirse en un guión.
Un programa es una secuencia de instrucciones que especifican cómo ejecutar un cómputo. El cómputo puede ser algo matemático, como solucionar un sistema de ecuaciones o determinar las raíces de un polinomio, pero también puede ser un cómputo simbólico, como buscar y reemplazar el texto de un documento o (aunque parezca raro) compilar un programa.
Las instrucciones (comandos, órdenes) tienen una apariencia diferente en lenguajes de programación distintos, pero existen algunas que son básicas, que se presentan en casi todo lenguaje, y que pueden agruparse en los siguientes conceptos:
Aunque sea difícil de creer, estos conceptos agrupan más o menos todas las instrucciones que hay en los lenguajes de programación. Todos los programas en existencia, sin importar su complejidad, son formulados exclusivamente con tales instrucciones. Así, la programación se puede describir como el proceso de dividir una tarea amplia y compleja en tareas cada vez más pequeñas hasta que éstas sean lo suficientemente sencillas como para ser ejecutadas con estas instrucciones básicas.
Quizás esta descripción sea un poco imprecisa, pero volveremos a este tema más adelante cuando hablemos de algoritmos .
La programación es un proceso complejo y, debido a que es realizada por seres humanos, a veces conlleva la aparición de errores. Por caprichos del destino, estos errores de programación se denominan bichos (del inglés ‘bugs’) y el proceso de buscarlos y corregirlos es llamado depuración (del inglés ‘debugging’).
Hay tres tipos de errores que pueden ocurrir en un programa: errores de sintaxis, errores en tiempo de ejecución y errores semánticos. Es muy útil distinguirlos para encontrarlos más rápido.
Python sólo puede ejecutar un programa si el programa está correcto sintácticamente; de lo contrario, el proceso falla y devuelve un mensaje de error. La palabra 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 el fin de toda oración debe llevar un punto. esta oración tiene un error de sintaxis. Esta otra oración también
Para la mayoría de los lectores unos pocos errores de sintaxis no representan un problema significativo, es por eso que pueden leer la poesía de e. e. cummings sin proferir algún mensaje de error. Python no es así. Si hay aunque sea un error de sintaxis en el programa, Python mostrará un mensaje de error y abortará la ejecución del programa. Durante las primeras semanas en su carrera de programador empleará bastante tiempo buscando errores de sintaxis. Sin embargo, conforme vaya adquiriendo experiencia, no tendrá tantos errores y los encontrará más rápido.
El segundo tipo de error es un error en tiempo de ejecución. Este error aparece sólo cuando se ejecuta un programa. Estos errores también se llaman excepciones porque indican que algo excepcional (y malo) ha ocurrido.
Los errores en tiempo de ejecución son raros en los programas simples que veremos en los primeros capítulos, por lo que pasará un buen tiempo antes de encontrar el primer error de este tipo.
El tercer tipo de error es el error semántico . Si hay un error semántico en su programa, el programa será ejecutado sin ningún mensaje de error, pero el resultado no será el deseado. El programa ejecutará exactamente lo que usted le dijo que ejecutara.
A veces ocurre que el programa escrito no es el programa que se tenía en mente. El sentido o significado del programa (su valor semántico) no es correcto. Identificar errores semánticos es difícil porque requiere trabajar al revés: comenzar por los resultados de salida y tratar de descifrar lo que el programa está realizando.
Una de las técnicas más importantes que usted aprenderá es la depuración. Aunque a veces es frustrante, la depuración es una de las partes de la programación intelectualmente más exigentes, desafiantes e interesantes.
La depuración es una actividad parecida a la labor realizada por detectives: se tienen que estudiar las pistas para inferir los procesos y eventos que han generado los resultados que se han encontrado.
La depuración es como una ciencia experimental. Una vez que se tiene conciencia de un error, se modifica el programa y se intenta nuevamente. Si la hipótesis fue la correcta se pueden predecir los resultados de la modificación y se estará más cerca a un programa correcto. Si la hipótesis fue errónea tendrá 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 el programa realice lo deseado. Esto quiere decir que el programa debe ser, desde el principio, un programa que funcione y que realice algo; a este programa se le hacen pequeñas modificaciones y se le depura mateniéndolo siempre funcionando.
Por ejemplo, aunque el sistema operativo Linux contenga miles de líneas de instrucciones, Linus Torvalds lo comenzó como un programa para explorar el microprocesador Intel 80386. Según Larry Greenfield,uno de los primeros proyectos de Linus fue un programa que intercambiaría la impresión de AAAA y BBBB. Este programa se convirtió en Linux(de The Linux Users’ Guide Versión Beta 1).
En capítulos posteriores se tratará más el tema de la depuración y de otras técnicas de programación.
Los Lenguajes naturales son los lenguajes hablados por seres humanos, como el español, el inglés y el francés. Estos no han sido diseñados artificialmente (aunque se trate de imponer cierto orden en ellos), pues se han desarrollado naturalmente.
Los Lenguajes formales son diseñados por seres humanos para 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 en programación:
Los Lenguajes de programación son lenguajes formales que han sido desarrollados para expresar cómputos.
Los lenguajes formales casi siempre tienen reglas sintácticas estrictas. Por ejemplo, 3+3=6 es una expresión matemática sintácticamente correcta, pero 3=+6$ no lo es. De la misma manera, H2O es una nomenclatura química sintácticamente correcta, pero 2Zz`` no lo es.
Existen dos clases de reglas sintácticas: unidades léxicas y estructura. Las unidades léxicas 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 (hasta donde sabemos) una unidad matemática aceptada. De manera similar, 2Zz no es formal porque no hay ningún elemento químico con la abreviación Zz.
La segunda clase de regla sintáctica está relacionada con la estructura de una sentencia; es decir, con el orden de las unidades léxicas. La estructura de la sentencia 3=+6$ no es aceptada porque no se puede escribir el símbolo de igualdad seguido del signo de la adición. Similarmente, las fórmulas moleculares tienen que mostrar el número de subíndice después del elemento, no antes.
Al leer una oración, sea en un lenguaje natural o una sentencia en un lenguaje formal, 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 se escucha una oración simple comoel otro zapato se cayó, se puede distinguir el predicadoel otro zapatoy el verbose cayó. Cuando se ha analizado la oración sintácticamente, se puede deducir el significado, o la semántica, de la oración. Si usted sabe lo que es un zapato y el significado de caer, comprenderá 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 lexicas, la estructura, la sintaxis y la semántica — también existen muchas diferencias:
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 la diferencia entre los lenguajes formales y los naturales es comparable a la diferencia entre la prosa y la poesía:
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 en consecuencia toma más tiempo dominarlos. Además, la estructura es muy importante, entonces usualmente no es una buena idea leerlo de arriba a abajo y de izquierda a derecha. En lugar de ésto, aprenda a separar las diferentes partes en su mente, identificar las unidades léxicas e interpretar la estructura. Finalmente, ponga atención a los detalles. La fallas de puntuación y la ortografía afectarán negativamente la ejecución de su programa.
Tradicionalmente el primer programa en un lenguaje nuevo se llama “¡Hola todo el mundo!” porque sólo muestra las palabras¡Hola todo el mundo!. En el lenguaje Python es así:
print "¡Hola todo el mundo!"
Este es un ejemplo de una sentencia print , la cual no imprime nada en papel, mas bien muestra un valor. En este caso, el resultado es las palabras:
¡Hola todo el mundo!
Las comillas señalan el comienzo y el final del valor; ellas no aparecen en el resultado.
Algunas personas evalúan la calidad de un lenguaje de programación por la simplicidad del programa¡Hola todo el mundo!. Si seguimos ese criterio, Python cumple con este cometido bastante bien.
Escriba en español una oración semánticamente comprensible pero sintácticamente incorrecta. Escriba otra oración que sea sintácticamente correcta pero que contenga errores semánticos.
Inicie la terminal de Python. Escriba 1 + 2 y luego presione la tecla Entrar. Python evalúa esta expresión, presenta el resultado, y enseguida muestra otro indicador. Considerando que el símbolo * es el signo de multiplicación y el doble símbolo ** es el signo de potenciación, realice ejercicios adicionales escribiendo diferentes expresiones y observando lo mostrado por el intérprete de Python. ¿Qué sucede si utiliza el signo de división (/)? ¿Son los resultados obtenidos los esperados? Explique.
Escriba 1 2 y presione la tecla Entrar. Python trata de evaluar esta expresión, pero no puede, porque la expresión es sintácticamente incorrecta. Así, Python responde con el siguiente mensaje de error:
File "<stdin>", line 1
1 2
^
SyntaxError: invalid syntax
Muchas veces Python indica la ubicación del error de sintaxis, sin embargo, no siempre es precisa, por lo que no proporciona suficiente información sobre cuál es el problema. De esta manera, el mejor antídoto es que usted aprenda la sintaxis de Python.
En este caso, Python protesta porque no encuentra signo de operación alguno entre los números.
Escriba tres ejemplos adicionales de cadenas que produzcan mensajes de error cuando se introducen en el indicador de Python. Explique por qué cada ejemplo no tiene una sintaxis de Python válida.
Escriba print 'hola'. Python ejecuta esta sentencia que muestra las letras h-o-l-a. Nótese que las comillas simples en los extremos de la cadena no son parte de la salida mostrada. Ahora escriba print '"hola"' y describa y explique el resultado.
Escriba print queso sin comillas. La salida será algo como esto:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'queso' is not defined
Este es un error en tiempo de ejecución; específicamente, es un NameError, y más específicamente, es un error porque el nombre queso no está definido. Si aún no sabe qué significa esto, lo sabrá pronto.
Escriba 'Esta es una prueba...' en el indicador de Python y presione la tecla Entrar. Observe lo que pasa. Ahora cree un guión de Python con el nombre prueba1.py que contenga lo siguiente (asegúrese de guardar el archivo antes de intentar correrlo):
'Este es una prueba...'
¿Qué pasa cuando corre este guión? Ahora cambie el contenido del guión a:
print 'Este es una prueba...'
y córralo de nuevo.
¿Qué pasó esta vez?
Cuando se escribe una <em>expresión</em> en el indicador de Python, ésta es evaluada y el resultado es mostrado en la línea siguiente. 'Esta es una prueba...' es una expresión, que se evalúa con 'Esta es una prueba...' (de la misma manera que 42 se evalúa con 42). Sin embargo, la evaluación de expresiones en un guión no se envía a la salida del programa, por lo que es necesario mostrarla explícitamente.