Ir al contenido principal

Entradas

Mostrando las entradas etiquetadas como Cursos de programación Python

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.

Capítulo 6

Iteración 6.1. Asignación múltiple Es posible que haya descubierto que es posible hacer mas de una asignación a una misma variable. El efecto de la nueva asignación es redirigir la variable de manera que deje de remitir al valor antiguo y empiece a remitir al valor nuevo. 1: bruno = 5 2: print bruno, 3: bruno = 7 4: print bruno La salida del programa es 5 7, ya que la primera vez que imprimimos Bruno su valor es 5, y la segunda vez su valor es 7. La coma al final de la primera sentencia print impide que se imprima una nueva l³nea en ese punto, por eso ambos valores aparecen en la misma línea. He aquí el aspecto de una asignacion multiple en un diagrama de estado: Cuando hay asignaciones multiples a una variable, es especialmente importante distinguir entre una sentencia de asignacion y una sentencia de igualdad. Puesto que Python usa el s³mbolo = para la asignacion, es tentador interpretar una sentencia como a = b como sentencia de igualdad. Pero no lo es. Para e...

6.2. La sentencia while

Una de las tareas para las que los computadores se usan con frecuencia es la automatización de tareas repetitivas . Repetir tareas similares o idénticas es algo que los computadores hacen bien y las personas no hacen tan bien. Hemos visto dos programas, nLineas y cuenta atrás, que usan la recursividad para llevar a cabo la repetición, que también se llama iteración. Por ser la iteración tan habitual, Python proporciona como lenguaje varias características que la hacen mas fácil. La primera característica que vamos a considerar es la sentencia while . Este es el aspecto de cuenta atrás con una sentencia while: 1: def cuenta_atras(n): 2: while n > 0: 3: print n 4: n = n-1 5: print "Despegando!" Como eliminamos la llamada recursiva, esta funcion no es recursiva. Casi podía leer una sentencia while como si fuera ingles (castellano “mientras”). Quiere decir que “Mientras n sea mayor que cero, continua mostrando el valo...

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.4. Tablas de dos dimensiones

Una tabla de dos dimensiones es una tabla en la que Usted elige una fila y una columna y lee el valor de la intersección. Un buen ejemplo es una tabla de multiplicar. Supongamos que desea imprimir una tabla de multiplicar para los valores del 1 al 6. Una buena manera de comenzar es escribir un bucle sencillo que imprima los múltiplos de 2, todos en una l³nea. 1: i = 1 2: while i <= 6: 3: print 2*i, '\t' , 4: i = i + 1 5: print La primera línea inicializa una variable lllamada i , que actuara como contador, o variable de bucle. Conforme se ejecuta el bucle, el valor de i se incrementa de 1 a 6. Cuando i vale 7, el bucle termina. Cada vez que se atraviesa el bucle, imprimimos el valor 2*i seguido por tres espacios. De nuevo, la coma de la sentencia print suprime el salto de línea. Despues de completar el bucle, la segunda sentencia print crea una línea nueva. La salida de este programa es: 2 4 6 8 10 12 Hasta ahora, bie...

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

6.6. Más encapsulación

Para dar mas ejemplos de encapsulación , tomaremos el código del final de la Sección 6.5 y lo envolveremos en una función: 1: def imprimeTablaMult(): 2: i = 1 3: while i <= 6: 4: imprimeMultiplos(i) 5: i = i + 1 6: El proceso que mostramos aquí es un plan de desarrollo habitual. Se desarrolla gradualmente el codigo añadiendo líneas fuera de cualquier funcion o en el interprete. Cuando conseguimos que funcionen, se extraen y se envuelven en una funcion. Este plan de desarrollo es especialmente si, al comenzar a escribir, no sabe como dividir el programa en funciones. Este enfoque le permite diseñarlo sobre la marcha.

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.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 [:]?...