Ir al contenido principal

Entradas

Mostrando las entradas etiquetadas como Pensar como programador

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...

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 p...

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 estruc...

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 obje...

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) ...

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...

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.

6.3. Tablas

Una de las cosas para las que resultan buenos los bucles es para generar datos tabulares . Antes de que los computadores estuvieran disponibles de forma masiva, la gente tenía que calcular a mano logaritmos, senos, cosenos y otras funciones matemáticas. Para facilitarlo, los libros de matemáticas contenían largas tablas donde aparecían los valores de estas funciones. Confeccionar estas tablas era una tarea lenta y pesada, y el resultado estaba lleno de erratas. Cuando los computadores aparecieron en escena, una de las primeras reacciones fue ¡Que bueno! Podemos usar los computadores para generar las tablas, así no habrá errores". Resulto cierto (casi), pero no se vio mas allá. Poco después los computadores y las calculadoras científicas se hicieron tan ubicuas que las tablas resultaron obsoletas. Bueno, casi. Resulta que para ciertas operaciones, los computadores usan tablas para obtener un valor aproximado, y luego ejecutan cálculos para mejorar la aproximación. En algunos ...

6.5. Encapsulado y generalización

Por “ encapsulado ” generalmente se entiende tomar una pieza de código y envolverla en una función, permitiéndole obtener las ventajas de todo aquello para lo que valen las funciones. Hemos visto dos ejemplos de encapsulado, cuando escribimos imprimeParidad en la Sección 4.5 y esDivisible en la Sección 5.4. Por “ generalización ” entendemos tomar algo específico, como imprimir los múltiplos de 2, y hacerlo mas general, como imprimir los múltiplos de cualquier entero. He aquí una función que encapsula el bucle de la sección anterior y la generaliza para imprimir múltiplos de n. def imprimeMultiplos(n): 1: i = 1 2: while i <= 6: 3: print n*i, '\t' , 4: i = i + 1 5: print Para encapsular , todo lo que hubimos de hacer fue añadir la primera línea, que declara el nombre de la función y la lista de parametros. Para generalizar , todo lo que tuvimos que hacer fue sustituir el valor 2 por el parametro n . Si llamamos a esta funcion con el argument...

Cadenas

7.1. Un tipo de datos compuesto Hasta el momento hemos visto tres tipos: int , float , y string . Las cadenas son cuantitativamente diferentes de los otros dos porque están hechas de piezas menores: caracteres. Los tipos que comprenden piezas menores se llaman tipos de datos compuestos. Dependiendo de que estemos haciendo, podemos querer tratar un tipo compuesto como una única cosa o acceder a sus partes. Esta ambigüedad es útil. El operador corchete selecciona un carácter suelto de una cadena. 1: >>> fruta = "banana" 2: >>> letra = fruta[1] 3: >>> 4: print letra La expresion fruta[1] selecciona el caracter numero 1 de fruta . La variable letra apunta al resultado. Cuando mostramos letra, nos encontramos con una sorpresa: a La primera letra de " banana " no es a . A no ser que usted sea un programador. Por perversas razones, los científicos de la computacion siempre empiezan a contar desde cero. La 0-sima letra (“cero...

7.2. Longitud

La función len devuelve el número de caracteres de una cadena: 1: >>> fruta = "banana" 2: >>> len(fruta) 3: 6 Para obtener la última letra de una cadena puede sentirse tentado a probar algo como esto: 1: longitud = len(fruta) 2: ultima = fruta[longitud] # ERROR! Eso no funcionara. Provoca un error en tiempo de ejecucion IndexError:string index out of range . La razon es que no hay una sexta letra en " banana ". Como empezamos a contar por cero, las seis letras estan numeradas del 0 al 5. Para obtener el ultimo caracter tenemos que restar 1 de longitud: 1: longitud = len(fruta) 2: ultima = fruta[longitud-1] De forma alternativa, podemos usar índices negativos, que cuentan hacia atrás desde el final de la cadena. La expresion fruta[-1] nos da la ultima letra. fruta[-2] nos da la penultima, y así.

7.4. Porciones de cadenas

Llamamos porción a un segmento de una cadena. La selección de una porción es similar a la selección de un carácter: 1: >>> s = "Pedro, Pablo, y María" 2: >>> print 3: s[0:5] 4: Pedro 5: >>> print s[7:12] 6: Pablo 7: >>> print 8: s[15:20] 9: María El operador [n:m] devuelve la parte de la cadena desde el enésimo carácter hasta el “enésimo”, incluyendo el primero pero excluyendo el ultimo. Este comportamiento contradice a nuestra intuicion; tiene mas sentido si imagina los índices se~nalando entre los caracteres, como en el siguiente diagrama: Si omite el primer índice (antes de los dos puntos), la porcion comienza al principio de la cadena. Si omite el segundo índice, la porcion llega al final de la cadena. Así: 1: >>> fruta = "banana" 2: >>> fruta[:3] 3: 'ban' 4: >>> 5: fruta[3:] 6: 'ana' ¿Que cree usted que significa s [:]?...

7.5. Comparación de cadenas

Los operadores de comparación trabajan sobre cadenas. Para ver si dos cadenas son iguales: 1: if palabra == "banana" : 2: print "S³, no tenemos bananas!" Otras operaciones de comparacion son utiles para poner palabras en orden alfabético: 1: if palabra < "banana" : 2: print "Tu palabra," + palabra + ", va antes de banana." 3: elif palabra > "banana" : 4: print "Tu palabra," + palabra + ", va despues de banana." 5: else : 6: print "Sí, no tenemos bananas!" Sin embargo, deber³a usted ser consciente de que Python no maneja las mayúsculas y minusculas como lo hace la gente. Todas las mayusuculas van antes de la minúsculas. Como resultado de ello: Tu palabra, Zapato, va antes de banana. Una forma comun de abordar este problema es convertir las cadenas a un formato estandar, como pueden ser las minusculas, antes de realizar la comparacion. Un prob...