Manual Phyton

136
Introducción al Phyton Que podemos hacer con Python una vez que aprendamos su sintaxis y filosofía de programación? Aplicaciones que se ejecutan en un servidor web (equivalentes a lo que se puede hacer con PHP, ASP.Net, JSP, Ruby) Más adelante cuando este más avanzado con el lenguaje Python le será muy útil solicitar una cuenta en Google App Engine y crear un sitio empleando como lenguaje de servidor el Python. También existen otras empresas de hosting que proveen como lenguaje de servidor el Python. Y cuando necesitemos ser más productivos en el desarrollo de sitios no podrá faltar el framework Django Aplicaciones de escritorio con interfaces visuales accediendo a componentes escritos en .Net (Microsoft), Qt, GTK, MFC, Swing (Java) etc. Programas no visuales que tengan como objetivo sistematizar procesos de administración del equipo (backup periódicos, borrado de archivos recursivos, búsquedad de archivos o contenidos de los mismos etc.) Aplicaciones para celulares. No podemos terminar con la introducción de este lenguaje sin codificar el famoso problema que muestra el 'Hola Mundo': print 'Hola Mundo' Problema resuelto Hola mundo Definición de variables Una variable almacena un valor de cierto tipo. En Python podemos definir variables de tipo: Numérica (entera) Numérica (flotante) Numérica (complejo) Cadena de caracteres Booleano Para definir una variable en Python solo debemos asignarle el valor, en dicho momento se define el tipo de variable según el valor asignado (Python es un lenguaje sensible a mayúsculas y minúsculas, por lo que debemos respetar esta característica):

description

Manual programación con phyton

Transcript of Manual Phyton

Page 1: Manual Phyton

Introducción al Phyton

Que podemos hacer con Python una vez que aprendamos su sintaxis y filosofía de programación?

Aplicaciones que se ejecutan en un servidor web (equivalentes a lo que se puede hacer con PHP, ASP.Net, JSP, Ruby) Más adelante cuando este más avanzado con el lenguaje Python le será muy útil solicitar una cuenta en Google App Engine y crear un sitio empleando como lenguaje de servidor el Python. También existen otras empresas de hosting que proveen como lenguaje de servidor el Python. Y cuando necesitemos ser más productivos en el desarrollo de sitios no podrá faltar el framework Django

Aplicaciones de escritorio con interfaces visuales accediendo a componentes escritos en .Net (Microsoft), Qt, GTK, MFC, Swing (Java) etc.

Programas no visuales que tengan como objetivo sistematizar procesos de administración del equipo (backup periódicos, borrado de archivos recursivos, búsquedad de archivos o contenidos de los mismos etc.)

Aplicaciones para celulares.

No podemos terminar con la introducción de este lenguaje sin codificar el famoso problema que muestra el 'Hola Mundo':

print 'Hola Mundo'

Problema resuelto

Hola mundo

Definición de variables

Una variable almacena un valor de cierto tipo. En Python podemos definir variables de tipo:

Numérica (entera)Numérica (flotante)Numérica (complejo)Cadena de caracteresBooleano

Para definir una variable en Python solo debemos asignarle el valor, en dicho momento se define el tipo de variable según el valor asignado (Python es un lenguaje sensible a mayúsculas y minúsculas, por lo que debemos respetar esta característica):

Variable entera:

edad=21

Variable flotante:

altura=1.92

Variable compleja:

valor=5+3j

Page 2: Manual Phyton

Cadena de caracteres (puede estar encerrada entre simples o dobles comillas):

nombre="Mario"

Booleano:

encontrado=False

Problema resuelto

Definir una variable de cada tipo y luego imprimirlas empleando la función print (como las estamos mostrando en una página HTML podemos imprimir el elemento HTML br luego de cada variable):

dad=21altura=1.92valor=5+3jnombre="Mario"encontrado=Falseprint edadprint "<br>"print alturaprint "<br>"print valorprint "<br>"print nombreprint "<br>"print encontradoprint "<br>"

Problema Propuesto

Definir una variable donde almacenar su nombre y en otra su edad, mostrar luego los valores almacenados con la leyenda previa que indique que representa:

Ver solución

nombre="ana"edad=25print "Nombre:"print nombreprint "<br>" print "Edad:"print edad

Definición de comentarios

En Python utilizamos el caracter # para indicar al intérprete que dicha línea es un comentario y no la debe procesar como una instrucción de Python.Es muy común utilizar comentarios para informar el objetivo del programa, su desarrollador, la lógica de los algorítmos empleados etc.

Veamos un progrma que utiliza comentarios:

Page 3: Manual Phyton

# Definición de tres variables enteras y una de tipo stringedad1=10edad2=4edad3=21nombre="pedro"

Podemos en la misma línea de código agregar comentarios:

edad3=23 #mayor de edad

Problema resuelto

Confeccionar una pantalla de presentación. Definir tres líneas de comentarios.

#Definición de tres títulos.#Los títulos deben ser de nivel h1.#Cada uno en una línea distinta.print '<h1>Primer titulo</h1>'print '<h1>Segundo titulo</h1>'print '<h1>Tercer titulo</h1>'

Problema Propuesto

Confeccionar una pantalla de presentación de un sitio. Definir varias líneas de comentarios indicando el nombre del programa, el programador y la fecha de la última modificación.

Ver solución#Programa: Foro Movil#Programador: Rodriguez Pablo#Fecha de última modificación: 22/07/2008print '<h1>Pantalla principal</h1>'

Operadores matemáticos

Python nos suministra los siguientes operadores matemáticos para trabajar con números enteros y flotantes:

+ suma- resta* multiplicación/ división de flotantes// división de enteros% resto de una división** exponenciación

Hay que tener en cuenta que si dividimos dos enteros con el símbolo / el resultado es un entero. Debe ser alguno de los dos números flotantes para que el resultado sea float.

Problema resuelto

Definir dos variables enteras e inicializarlas con los valores 7 y 2.5 respectivamente. Luego imprimir la suma, resta, multiplicación, resto de la división y el resultado de la división como entero y como flotante.

valor1=7valor2=2.5

Page 4: Manual Phyton

suma=valor1+valor2print 'La suma es:'print sumaprint '<br>'resta=valor1-valor2print 'La resta es:'print restaprint '<br>'multiplicacion=valor1*valor2print 'El producto es:'print multiplicacionprint '<br>'div1=valor1/valor2print 'La división con resultado entero:'print div1print '<br>'div2=valor1//valor2print 'La división con resultado float:'print div2print '<br>'resto=valor1%valor2print 'El resto:'print restoprint '<br>'

solución:La suma es: 9.5 La resta es: 4.5 El producto es: 17.5 La división con resultado entero: 2.8 La división con resultado float: 2.0 El resto: 2.0

Problema Propuesto

Mostrar el resultado de elevar el número 2 al cuadrado y al cubo.

Ver solucióncuadrado=2**2print 'Cuadrado:'print cuadradoprint '<br>'cubo=2**3print 'Cubo:'print cubo

Estructura condicional if

Igual que otros lenguajes cuando tenemos que tomar una decisión en nuestro programa debemos utilizar la estructura if.Algo muy importante en el lenguaje Python que no lo tienen otros lenguajes es que la indentación es obligatoria e indica las intrucciones contenidas en un if.

Analicemos el siguiente ejemplo:

Page 5: Manual Phyton

nombre='juan'edad=15if edad<18: print nombre print ' es menor de edad.<br>'print 'Fin del programa'

La estructura if contiene una condición, si dicha condición se verifica verdadera luego se ejecutan todas las instrucciones que se encuentran indentadas (es decir corridas a derecha) Es muy común utilizar una indentación de 4 espacios.

En nuestro ejemplo la instrucción:

print 'Fin del programa'

se encuentra fuera de la estructura if.

Si la condición se verifica verdadera luego se ejecutan las intrucciones:

print nombre print ' es menor de edad.<br>'

Es obligatorio luego de la condición del if disponer los dos puntos

if edad<18:

También similar a otros lenguajes la estructura condicional if tiene una segunda parte que es el else, dicha sección se ejecuta si la condición se verifica falsa.

nombre='juan'edad=15print nombreif edad<18: print ' es menor de edad.<br>'else: print ' es mayor de edad.<br>'print 'Fin del programa'

Nuevamente tener en cuenta que las instrucciones que se indiquen por el else deben estar corridas a derecha (indentadas).La palabra clave else requiere también los dos puntos

else:

Problema resuelto

Generar un número aleatorio comprendido entre 1 y 20. Luego mostrar si el valor generado tiene uno o dos dígitos.Para generar un valor aleatorio hay una librería que debemos importar (veremos más adelante el concepto de módulos)

import random

Luego podemos llamar la función randint de dicho módulo, esta función requiere dos valores enteros y nos devuelve otro valor entero comprendido entre ellos (lo selecciona de forma aleatoria, es decir al azar)

x=random.randint(1,20)

import random

Page 6: Manual Phyton

x=random.randint(1,20)print xprint '<br>'if x<10: print 'El valor generado tiene un digito'else: print 'El valor generado tiene dos digitos' solución:7 El valor generado tiene un digito

Problema Propuesto

Inicializar una variable con un valor entero comprendido entre 1 y 100. Generar luego un valor aleatorio también comprendido entre 1 y 100. Mostrar un mensaje si el valor generado coincide con el valor de la variable (en Python para ver si dos variable almacenan el mismo valor se utiliza el operador relacional == )

Solucion;import random

elegido=25x=random.randint(1,100)print xprint '<br>'if elegido==x: print 'El valor generado coincide con la variable'else: print 'El valor generado no coincide con la variable'

Operadores relacionales

En Python contamos con los siguientes operadores relacionales:

== Igualdad

!= Desigualdad

< menor

<= menor o igual

> mayor

>=mayor o igual

Cuando disponemos una condición en una estructura condicional debemos utilizar alguno de estos seis operadores relacionales.Toda condición debe tener un operando o valor, luego un operador relacional y finalmente otro operando o valor.

Todas estas condiciones son válidas:

if edad==18:

if edad<=18:

Page 7: Manual Phyton

if edad!=50:

if edad>=18:

if valor1<valor2:

if valor1>valor2:

Problema resuelto

Inicialzar dos variables con valores aleatorios comprendidos entre 1 y 10.Mostrar un mensaje si los dos valores generados son iguales.Mostrar un mensaje si el primer valor es menor a 5.Mostrar otro mensaje si el segundo valor es mayor a 5.

import random

valor1=random.randint(1,10)valor2=random.randint(1,10)print 'Primer valor:'print valor1print '<br>'print 'Segundo valor:'print valor2print '<br>'if valor1==valor2: print 'Los dos valores son iguales.<br>'if valor1<5: print 'El primer valor es inferior a 5.<br>'if valor2>5: print 'El segundo valor es superior a 5.<br>'

Solución:Primer valor: 6 Segundo valor: 10 El segundo valor es superior a 5.

Estructura condicional if anidada

En ocaciones cuando hay más de dos caminos posibles es necesario implementar estructuras condicionales anidadas, es decir por la rama del verdadero o falso (else:) disponemos otras estructuras condicionales.

Debemos tener cuidado con la indentación del código para evitar errores.

Veamos un ejemplo que requiere utilizar estructuras condicionales anidadas. Generaremos tres números aleatorios y luego imprimiremos el mayor de los tres:

import random

x1=random.randint(1,100)x2=random.randint(1,100)x3=random.randint(1,100)print x1print '-'

Page 8: Manual Phyton

print x2print '-'print x3print '<br>'print 'El mayor es:'if x1>x2: if x1>x3: print x1 else: print x3else: if x2>x3: print x2 else: print x3

Como podemos observar por el bloque del verdadero del primer if tenemos otra estructura condicional (debemos indentar cada estructura condicional):

if x1>x2: if x1>x3: print x1 else: print x3

Problema resuelto

Generar un valor aleatorio entre 1 y 1000. Luego imprimir un mensaje indicando cuantos dígitos tiene.

import random

x1=random.randint(1,1000)print x1print '<br>'if x1<10: print 'Tiene 1 dígito'else: if x1<100: print 'Tiene 2 dígitos' else: if x1<1000: print 'Tiene 3 dígitos' else: print 'Tiene 4 dígitos'

solución:436 Tiene 3 dígitos

Problema Propuesto

Generar un valor aleatorio entre -10 y 10. Mostrar un mensaje si el valor generado es negativo, nulo o positivo.

Para generar un valor aleatorio en ese rango debemos plantear la siguiente expresión:

Page 9: Manual Phyton

x=-10+random.randint(0,20)

solución;

import random

x=-10+random.randint(0,20)print xprint '<br>'if x<0: print 'Numero negativo'else: if x==0: print 'Numero nulo' else: print 'Numero positivo'

Operadores lógicos

En Python contamos con los siguientes peradores lógicos:

and (y)

or (o)

not (no)

Los operadores lógicos nos permiten agrupar condiciones simples en una estructura condicional, esto nos facilita la implementación de algoritmos más compactos y comprensibles.

Cuando unimos dos condiciones simples con el operador lógico 'and' ambas condiciones deben verificarse como verdaderas para que la condición compuesta se verifique verdadera. Por ejempo si tenemos que mostrar un mensaje si la edad de una persona está comprendida entre 12 y 18 años podemos plantearla con una única estructura condicional:

if edad>=12 and edad<=18: print 'Edad comprendida entre 12 y 18'

Estamos diciendo si la variable 'edad' tiene un valor mayor o igual a 12 y además la variable edad tiene un valor menor o igual a 18 luego ejecutar la rama del verdadero.

La condición anterior nos evita tener que implementar dos estructuras condicionales:

if edad>=12: if edad<=18: print 'Edad comprendida entre 12 y 18'

El operador lógico 'or' hace que con que alguna de las condiciones sea verdadera luego ejecute el bloque del verdadero.

if x1<5 or x2<5:

Se ejecuta la rama del verdadero si al menos una de las dos variables es menor a 5.

El operador not invierte el valor de una condición:

if not x1>x2:

Page 10: Manual Phyton

Si x1 no es mayor a x2 luego ejecuta la rama del verdadero de la estructura condicional.

Podemos plantear condiciones con más de dos condiciones simples:

if x1<0 or x2<0 or x3<0:

Si x1 o x2 o x3 tienen un valor inferior a cero luego se ejecuta la rama del verdadero del if.

Problema resuelto

Generar tres números aleatorios y luego imprimir el mayor de los tres. Emplear condiciones compuestas donde sea posible.

import random

x1=random.randint(1,100)x2=random.randint(1,100)x3=random.randint(1,100)print x1print '-'print x2print '-'print x3print '<br>'print 'El mayor es:'if x1>x2 and x1>x3: print x1else: if x2>x3: print x2 else: print x3

Resultado:100 - 24 - 25 El mayor es: 100

Problema Propuesto

Generar 3 números aleatorios entre 1 y 100. Mostrar un mensaje si todos son superiores a 10.

import random

x1=random.randint(1,100)x2=random.randint(1,100)x3=random.randint(1,100)print x1print '-'print x2print '-'print x3print ''if x1>10 and x2>10 and x3>10: print 'Todos los valores son superiores a 10'

Page 11: Manual Phyton

Estructura condicional if-elif

Esta estructura condicional es una forma más elegante de disponer estructuras condicionales anidadas.

Veamos como lo hacemos con estructuras condicionales anidadas y luego utilizando la sintaxis if/elif:(problema: generar un número aleatorio entre 1 y 1000, luego imprimir la cantidad de dígitos del número generado)

import random

x=random.randint(1,1000)print xprint '<br>'if x<10: print 'Tiene 1 dígito'else: if x<100: print 'Tiene 2 dígitos' else: if x<1000: print 'Tiene 3 dígitos' else: print 'Tiene 4 dígitos'

Luego con la estructura condicional if/elif:

import random

x=random.randint(1,1000)print xprint '<br>'if x<10: print 'Tiene 1 dígito'elif x<100: print 'Tiene 2 dígitos'elif x<1000: print 'Tiene 3 dígitos'else: print 'Tiene 4 dígitos'

Problema resuelto

Almacenar en una variable entera la nota de un alumno, luego mostrar un mensaje si está promocionado (nota>=9), regular (nota>=4) o reprobado (nota<4)

nota=7print 'Nota:'print notaprint '<br>'if nota>=9: print 'Promocionado'elif nota>=4: print 'Regular'else: print 'Reprobado'

Resultado:Nota: 7 Regular

Page 12: Manual Phyton

Problema Propuesto

Generar un valor aleatorio comprendido entre 1 y 5. Luego mostrar en castellano el valor generado.

import random

x=random.randint(1,5)if x==1: print 'uno'elif x==2: print 'dos'elif x==3: print 'tres'elif x==4: print 'cuatro'elif x==5: print 'cinco'

Estructura repetitiva while

Las estructuras repetitivas nos permiten ejecutar un bloque de instrucciones varias veces, dependiendo de una condición.

La estructura while repite el bloque de instrucciones mientras la condición se verifique verdadera.

Si queremos mostrar los números del 1 al 100 con estructuras secuenciales el proceso es largo y engorroso, utilizando una estructura repetitiva el algoritmo es muy compacto:

print 'Números del 1 al 100:'x=1while x<=100: print x print '-' x=x+1print 'Fin'

Es importante recordar y remarcar que las instrucciones que se ejecutan en la estructura repetitiva while son todas las que se encuentran indentadas a derecha (cuatro espacios más a la derecha de la instrucción while)

La variable x se inicializa previo a la estructura while con el valor 1. La primera vez que se ejecuta la condición del while se verifica verdadera, ya que 1 es menor o igual a 100.

Dentro de la estructura repetitiva mostramos el contenido de la variable x, luego imprimimos un guión y finalmente incrementamos la variable x con el valor actual más uno.

La impresión de la cadena 'Fin' se ejecuta una vez finalizada la estructura repetitiva while.

Problema resuelto

Mostrar la tabla de multiplicar del 2 (del 2 al 20) empleando una estructura repetitiva while.

x=2print 'Tabla del 2:'while x<=20:

Page 13: Manual Phyton

print x print '<br>' x=x+2

Resultado:

Tabla del 2: 2 4 6 8 10 12 14 16 18 20

Problema Propuesto

Generar un valor aleatorio entre 100 y 200. Luego mostrar los números comprendidos entre 1 y el valor generado.

import random

x=random.randint(100,200)print 'Número final:'print xprint '<br>'cont=1while cont<=x: print cont print '-' cont=cont+1

solución:mport random

x=random.randint(100,200)print 'Número final:'print xprint '<br>'cont=1while cont<=x: print cont print '-' cont=cont+1

Funciones

La estructura fundamental de programación de los lenguajes estructurados son las funciones. Una función es un conjunto de instrucciones que se la invoca mediante un nombre y que luego de ejecutado el algoritmo puede retornar un valor.

Un programa estructurado no es más que un conjunto de funciones que en conjunto resuelven un problema complejo.

Page 14: Manual Phyton

Veamos la sintaxis en Python para definir y llamar a una función:

def presentacion(): print 'Primer mensaje.<br>' print 'Segundo mensaje.<br>'

def fin(): print 'Ultimo mensaje.'

presentacion()fin()

Para definir una función utilizamos la palabra clave 'def' seguida por el nombre de la función, luego si no tiene parámetros como este caso debe ir paréntesis abiertos y cerrados y dos puntos. Seguidamente las instrucciones de la función se indentan a derecha.

def presentacion(): print 'Primer mensaje.<br>' print 'Segundo mensaje.<br>'

Una función se ejecuta cuando se la llama por su nombre:

presentacion()

Es importante notar que primero debemos declarar la función y luego llamarla.

Una función puede tener parámetros de entrada, por ejemplo si queremos una función que reciba dos enteros y luego nos imprima el mayor, el algoritmo es el siguiente:

def imprimirmayor(valor1,valor2): if valor1>valor2: print valor1 else: print valor2

imprimirmayor(4,5)print '<br>'x1=20x2=30imprimirmayor(x1,x2)

Los parámetros de la función se indican en la cabecera de la función separados por comas.Cuando llamamos a la función estamos obligados a enviarle datos a los dos parámetros.

Podemos enviarle directamente los valores:

imprimirmayor(4,5)

O podemos enviarle variables previamente inicializadas:

x1=20x2=30imprimirmayor(x1,x2)

Como podemos notar con este ejemplo una función puede ser llamada más de una vez (en este caso la llamamos dos veces)

Problema resuelto

Page 15: Manual Phyton

Confeccionar una función que reciba un entero y luego imprima la tabla de multiplicar de dicho valor (por ejemplo si recibe un 3 luego debe mostrar del 3 hasta el 30 de 3 en 3)

def mostrartabla(num): inicio=num fin=num*10 while inicio<=fin: print inicio print '-' inicio=inicio+num mostrartabla(3)

Resultado:

3 - 6 - 9 - 12 - 15 - 18 - 21 - 24 - 27 - 30 –

Problema Propuesto

Desarrollar una función que reciba dos enteros y nos muestre todos los valores comprendidos entre ellos (el segundo parámetro siempre debe ser mayor al primero)

def rangovalores(v1,v2): inicio=v1 while inicio<=v2: print inicio print '<br>' inicio=inicio+1

rangovalores(2,20)

Funciones con retorno de dato

Hay muchas situaciones donde queremos que la función luego de ejecutarse retorne un valor y se almacene en una variable desde donde la llamamos.Por ejemplo si necesitamos una función que reciba tres enteros y nos retorne el mayor la sintaxis será la siguiente:

def retornarmayor(x1,x2,x3): if x1<x2 and x1<x3: return x1 elif x2<x3: return x2 else: return x3

may=retornarmayor(4,5,3)print may

Como podemos observar la instrucción return indica el valor devuelto por la función.

El valor retornado se almacena en una variable:

Page 16: Manual Phyton

may=retornarmayor(4,5,3)

Podemos inclusive mostrar directamente el valor retornado por la función:

print retornarmayor(40,5,3)

O utilizarlo en una condición:

if retornarmayor(40,5,3)<20: print 'El valor devuelto es mayor a 20'

Problema resuelto

Confeccionar una función que reciba tres enteros y nos retorne la suma de dichos valores.

def sumar(x1,x2,x3): su=x1+x2+x3 return su

total=sumar(10,30,42)print total

Resultado:82

Problema Propuesto

Desarrollar una función que reciba tres enteros y nos retorne la suma de los dos más grandes.

Solución:def sumarmayores(x1,x2,x3): if x1>x2 and x1>x3: if x2>x3: return x1+x2 else: return x1+x3 elif x2>x3: if x3>x1: return x2+x3 else: return x2+x1 else: if x2>x1: return x3+x2 else: return x3+x1

print sumarmayores(100,200,30)

Estructura de datos tipo tupla

Hasta ahora hemos empleado variables que permiten almacenar un único valor. En Python existen varias estructuras de datos que permiten almacenar un conjunto de datos.

Page 17: Manual Phyton

La primera que presentaremos es la tupla:Una tupla es una colección de datos no necesariamente del mismo tipo que se los accede por medio de subíndices.

Definición de una tupla:

tupla1=('juan',18,1.92)

Hemos definido una tupla de tres elementos. El primer elemento es de tipo cadena de caracteres, el segundo un entero y finalmente un valor flotante.

Cada elemento de una tupla se los separa por una coma.

Para acceder a los elementos lo hacemos por medio del nombre de la tupla y un subíndice numérico:

print tupla1[0]

Los elementos de la tupla comienzan a numerarse a partir de cero y utilizamos los corchetes para hacer referencia al subíndice.

Si queremos en algún momento saber la cantidad de elementos de una tupla debemos llamar la función len:

print len(tupla1) #imprime un 3

con dicha función podemos disponer una estructura repetitiva para imprimir todas las componentes de la tupla con el siguiente algoritmo:

tupla1=('juan',18,1.92)indice=0while indice<len(tupla1): print tupla1[indice] indice=indice+1

Veremos en el próximo concepto que hay una estructura repetitiva que nos facilita recorrer los elementos de una tupla.

Una vez definida la tupla no se pueden modificar los valores almacenados.

La función print puede recibir como parámetro una tupla y se encarga de mostrarla en forma completa:

print tupla1

De todos modos cuando tenemos que acceder a algún elemento de la tupla debemos hacerlo mediante un subíndice entre corchetes.

La característica fundamental de una tupla es que una vez creada no podemos modificar sus elementos, ni tampoco agregar o eliminar.

Problema resuelto

Definir dos tuplas que almacenen en una los nombres de los meses y en otra la cantidad de días que tiene cada mes del año. Luego mostrar el contenido almacenado en las mismas.

meses=('enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre')cantidaddias=(31,28,31,30,31,30,31,31,30,31,30,31)

Page 18: Manual Phyton

indice=0while indice<len(meses): print meses[indice] print ':' print cantidaddias[indice] print '<br>' indice=indice+1

Resultado:enero : 31 febrero : 28 marzo : 31 abril : 30 mayo : 31 junio : 30 julio : 31 agosto : 31 septiembre : 30 octubre : 31 noviembre : 30 diciembre : 31

Problema Propuesto

Definir una tupla que almacene 5 enteros. Implementar un algoritmo que imprima la suma de todos los elementos.

Ver solucióntupla1=(6,33,56,3,45)suma=0indice=0while indice<len(tupla1): suma=suma+tupla1[indice] indice=indice+1print 'El contenido de la tupla es:'print tupla1print '<br>'print 'La suma es:'print suma

Estructura repetitiva for in para recorrer una tupla

Para recorrer una tupla es muy común utilizar la estructura repetitiva for.Veamos con un ejemplo la sintaxis de esta estructura repetitiva:

tupla1=('juan',23,1.92)for elemento in tupla1: print elemento print '<br>'

Como podemos ver la instrucción for requiere una variable (en este ejemplo llamada elemento), luego la palabra clave in y por último la tupla. El bloque del for se ejecuta tantas veces como elementos tenga la tupla, y en cada vuelta del for la variable elemento almacena un valor de la tupla1.

Esta estructura repetitiva se adapta mucho mejor que el while para recorrer este tipo de estructuras de datos.

Page 19: Manual Phyton

Problema resuelto

Definir una tupla con 5 valores enteros. Imprimir los valores mayores o iguales a 18.

tupla1=(45,34,2,56,1)for elemento in tupla1: if elemento>=18: print elemento print '<br>'

Resultado:45 34 56

Problema Propuesto

Definir una tupla con 10 edades de personas. Imprimir la cantidad de personas con edades superiores a 20.

tupla1=(45,78,3,56,3,45,34,2,56,1)cantidad=0for elemento in tupla1: if elemento>20: cantidad=cantidad+1print 'Cantidad de personas con edades superiores a 20:'print cantidad

Porciones de tuplas

El lenguaje Python nos permite rescatar una "porción" de una tupla, es decir un trozo de la misma.Si tenemos la siguiente tupla:

tupla1=(1,7,20,40,51,3)tupla2=tupla1[0:4]print tupla2

El resultado es una tupla con cuatro valores:

(1,7,20,40)

Es decir indicamos como subíndice un rango de valores, en este caso desde la posición 0 hasta la posición 4 sin incluirla.

Podemos no indicar alguno de los dos rangos:

tupla1=(1,7,20,40,51,3)tupla2=tupla1[3:]print tupla2

El resultado es una tupla con tres valores, desde la posición 3 hasta el final de la tupla:

(40, 51, 3)

Page 20: Manual Phyton

En caso de no indicar el primer rango:

tupla1=(1,7,20,40,51,3)tupla2=tupla1[:2]print tupla2

El resultado es una tupla con dos valores, desde el principio de la tupla hasta la posición 2 sin incluirla:

(1, 7)

Problema resuelto

Definir una tupla con los nombres de los meses. Generar dos tuplas que almacenen los primeros 6 meses la primera y los siguientes 6 meses la segunda.

meses=('enero','febrero','marzo','abril','mayo','junio','julio','agosto','septiembre','octubre','noviembre','diciembre')tupla1=meses[:6]tupla2=meses[6:]print tupla1print '<br>'print tupla2

Resultado:('enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio') ('julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre')

Problema Propuesto

Almacenar en una tupla 5 nombres. Luego generar un valor aleatorio entre 2 y 4. Copiar a una tupla el nombre de la posición indicada por el valor aleatorio y los nombres que se encuentran en la posición anterior y posterior.

Ver solución

import random

nombre=('juan','ana','luis','carlos','roman')ale=random.randint(1,3)tresnombres=nombre[ale-1:ale+2]print tresnombres

Estructura de datos tipo cadena de caracteres (string)

Una cadena de caracteres permite almacenar un conjunto de caracteres. Su funcionamiento es similar a una tupla.Para inicializar un string utilizamos el operador de asignación.

nombre='Juan Pablo'

Podemos utilizar las comillas simples o dobles para su inicialización:

Page 21: Manual Phyton

mail='[email protected]'

o

mail="[email protected]"

Para conocer el largo de un string podemos utilizar la función len:

print len(mail)

Para acceder a un caracter particular del string lo hacemos indicando un subíndice entre corchetes:

print mail[0] #Imprimimos el primer caracter

El lenguaje Python nos permite rescatar una "porción" de un string con la misma sintaxis que trabajamos las tuplas:

nombre='Jose Maria'print nombre[1:4] #oseprint nombre[:4] #Joseprint nombre[5:] #Maria

Los string son inmutables, es decir que no podemos modificar su contenido luego de ser inicializados:

titulo='Administracion'titulo[0]='X' # Esto produce un error

Esto no significa que no podemos utilizar la variable para que referencie a otro string:

nombre='Jose'print nombrenombre='Ana'print nombre

Para concatenar string Python permite utilizar el operador +.Si tenemos tres string y queremos almacenar sus contenidos en un cuarto string podemos codificarlo de la siguiente manera:

cadena1='uno'cadena2='dos'cadena3='tres'total=cadena1+cadena2+cadena3print total #unodostres

También Python define el operador * para los string. El resultado de multiplicar un string por un entero es otro string que repite el string original tantas veces como indica el número.

#si queremos un string con 80 caracteres de subrayado, la forma más sencilla es utilizar la siguiente expresión:separador='_'*80print separador

Los operadores relacionales definidos para los string son:

> Mayor >= Mayor o igual < Menor <= Menor o igual== Igual!= Distinto

Page 22: Manual Phyton

Si queremos saber si un string es mayor alfabéticamente que otro utilizamos el operador >

nombre1='CARLOS'nombre2='ANABEL'if nombre1>nombre2: print nombre1+' es mayor alfabéticamente que '+nombre2

si queremos saber si dos variables tienes en mismo contenido:

nombre1='CARLOS'nombre2='CARLOS'if nombre1==nombre2: print 'Las dos variables tienen el mismo contenido:'+nombre1

Problema resuelto

Elaborar una función que reciba un string y retorne la cantidad de vocales que tiene.

def cantidadvocales(cadena): cant=0 for letra in cadena: if letra=='a': cant=cant+1 if letra=='e': cant=cant+1 if letra=='i': cant=cant+1 if letra=='o': cant=cant+1 if letra=='u': cant=cant+1 if letra=='A': cant=cant+1 if letra=='E': cant=cant+1 if letra=='I': cant=cant+1 if letra=='O': cant=cant+1 if letra=='U': cant=cant+1 return cant

print 'Cantidad de vocales en la palabra Hola:'print cantidadvocales('Hola')print '<br>'print 'Cantidad de vocales en la palabra Computadora:'print cantidadvocales('Computadora')

Resultado:Cantidad de vocales en la palabra Hola: 2 Cantidad de vocales en la palabra Computadora: 5

Problema Propuesto

Page 23: Manual Phyton

Elaborar las siguientes funciones:- Una función que reciba un string y nos retorne el primer caracter.- Una función que reciba un apellido y un nombre, y nos retorne un único string con el apellido y nombre concatenados y separados por una coma.- Una función que reciba dos string y nos retorne el que tiene menos caracteres.

Ver solución

def primercaracter(cadena): return cadena[0]

def concatenar(apellido,nombre): return apellido+','+nombre

def menor(cadena1,cadena2): if len(cadena1)<len(cadena2): return cadena1 else: return cadena2

cad='Hola Mundo'print 'Primer caracter de '+cad+' es '+primercaracter(cad)print '<br>'nom='juan'ape='rodriguez'print 'Apellido y nombre concatenados:'+concatenar(ape,nom)cad1='Hola'cad2='Fin'print '<br>'print 'De: '+cad1+' y '+cad2+' tiene menos caracteres '+menor(cad1,cad2)

Estructura de datos tipo lista

Una lista es una colección de datos no necesariamente del mismo tipo que se los accede por medio de subíndices. La diferencia fundamental de una lista con una tupla es que podemos modificar la estructura luego de haberla creado.

Hay varias formas de crear una lista, la primera y más sencilla es enumerar sus elementos entre corchetes y separados por coma:

lista1=['juan','ana','luis']

Para acceder a sus elementos lo hacemos indicando un subíndice subíndice:

print lista1[0]

Como decíamos la diferencia con una tupla (son inmutables) es que podemos modificar la lista luego de creada:

lista1=[10,15,20]print lista1print '<br>'lista1[0]=700 # modificamos el valor almacenado en la primer componente de la lista.print lista1

De forma similar a las tuplas y string la función len nos informa de la cantidad de elementos que contiene la lista:

Page 24: Manual Phyton

lista1=[10,15,20]print len(lista1) # imprime un 3

Es muy común emplear la estructura for in para recorrer y rescatar cada elemento de la lista, la variable elemento almacena en cada ciclo del for un elemento de la lista1, comenzando por el primer valor:

lista1=['juan',23,1.92]for elemento in lista1: print elemento print '<br>'

Si queremos saber si un valor se encuentra en una lista existe un operador llamado in:

lista1=[12,45,1,2,5,4,3,55]if 1 in lista1: print 'El valor 1 está contenido en la lista 'else: print 'El valor 1 no está contenido en la lista 'print lista1

Python define los operadores + y * para listas, el primero genera otra lista con la suma de elementos de la primer y segunda lista. El operador * genera una lista que repite tantas veces los elementos de la lista como indica el valor entero seguido al operador *.

lista1=[2,4,6,8]lista2=[10,12,14,16]listatotal=lista1+lista2print listatotal

Luego empleando el operador *:

lista1=['juan','carlos']producto=lista1*3print producto

El resultado de este algoritmo es:

['juan', 'carlos', 'juan', 'carlos', 'juan', 'carlos']

También con listas podemos utilizar el concepto de porciones que nos brinda el lenguaje Python:

lista=[2,4,6,8,10]print lista[2,4] #[6, 8]print lista[:3] #[2, 4, 6]print lista[3:] #[8, 10]

Como vimos podemos modificar el contenido de elementos de la lista asignándole otro valor:

lista=[2,4,6]lista[1]=10print lista #[2, 10, 6]

Podemos borrar elementos de la lista utilizando la función del:

lista=[2,4,6]del(lista[1])print lista #[2, 6]

Además podemos utilizar porciones para borrar un conjunto de elementos de la lista:

lista=[2,4,6]

Page 25: Manual Phyton

del(lista[1:])print lista #[2]

También podemos añadir elementos a una lista:

lista=[5,10,11,12]lista[1:1]=[6,7,8,9]print lista #[5,6,7,8,9,10,11,12]

Problema resuelto

Definir una lista con edades de personas, luego borrar todos los elementos que sean menores a 18.

edades=[23,5,67,21,12,4,34]indice=0while indice<len(edades): if edades[indice]<18: del(edades[indice]) else: indice=indice+1print edades

Resultado:[23, 67, 21, 34]

Problema Propuesto

Definir una lista con un conjunto de nombres, imprimir la cantidad de comienzan con la letra a:

nombres=['ariel','marcos','ana','luis','pedro','andres']cant=0for nom in nombres: if nom[0]=='a': cant=cant+1print nombresprint '<br>'print 'Cantidad de nombres que comienzan con a es:'print cant

Indices negativos en tuplas, listas y string

Hemos visto que en Python accedemos a los elementos de una lista, tupla y string mediante un subíndice que comienza a numerarse a partir de cero:

tupla=(2,4,6,8,10)print tupla[0] # 2lista=[2,4,6,8,10]print lista[0] # 2cadena='hola'print cadena[0] # h

Si queremos acceder a la última componente podemos hacerlo:

tupla=(2,4,6,8,10)print tupla[len(tupla)-1] # 10

Page 26: Manual Phyton

Pero Pyton tiene integrado en el lenguaje el acceso de los elementos de la secuencia mediante índices negativos, por ejemplo si queremos acceder a la última componente luego podemos hacerlo con la siguiente sintaxis:

tupla=(2,4,6,8,10)print tupla[-1] # 10lista=[2,4,6,8,10]print lista[-1] # 10cadena='hola'print cadena[-1] # a

Es mucho más cómodo utilizar esta segunda forma para acceder a los elementos de una lista, tupla o cadena de caracteres.

Si queremos imprimir los elementos de una tupla en forma inversa (es decir desde el último elemento hasta el primero) podemos hacerlo con el siguiente algoritmo:

tupla=(2,4,6,8,10)indice=-1for x in range(0,len(tupla)): print tupla[indice] # 10 8 6 4 2 indice=indice-1

Problema resuelto

Inicializar una variable con un valor aleatorio comprendido entre 1 y 1000000, verificar si es capicúa, es decir si se lee igual de izquierda a derecha como de derecha a izquierda.

import random

valor=random.randint(1,1000000)print valorprint '<br>'cadena=str(valor)indice=-1iguales=0for x in range(0,len(cadena)/2): if cadena[x]==cadena[indice]: iguales=iguales+1 indice=indice-1if iguales==(len(cadena)/2): print 'Es capicua'else: print 'No es capicua'

Resultado:561790 No es capicúa

Problema Propuesto

Definir una lista con una serie de elementos. Intercambiar la información del primero con el último de la lista.

Page 27: Manual Phyton

Ver soluciónlista=['juan','ana','luis','pedro']print listaprint '<br>'aux=lista[0]lista[0]=lista[-1]lista[-1]=auxprint lista

Estructura de datos tipo diccionario

Las estructuras de datos vistas hasta ahora (tuplas y listas) utilizan un entero como subíndice. La estructura de datos tipo diccionario utiliza una clave para acceder a un valor. El subíndice puede ser un entero, un string etc.

Un diccionario vincula una clave y un valor.

Si queremos almacenar la cantidad de productos que tenemos en stock podemos implementar un diccionario donde utilizamos como clave el nombre del producto y como valor la cantidad de productos disponibles.

Podemos definir un diccionario con la siguiente sintaxis:

productos={'manzanas':23,'peras':50,'papas':120}

Luego si queremos acceder a la cantidad de productos en stock utilizamos como subíndice el nombre del producto:

print productos['manzanas']

La línea anterior produce como resultado el valor 23.

Mediante un diccionario asociamos para toda clave un valor.

Podemos borrar cualquier entrada dentro del diccionario empleando la siguiente sintaxis:

del(productos['manzana'])

Luego si imprimimos el diccionario en forma completa tenemos como resultado que ya no contiene la entrada 'manzana':

print propductos

{'peras': 50, 'papas': 120}

Podemos modificar el valor asociado a una clave mediante una simple asignación:

productos['papas']=5

Luego si imprimimos el diccionario obtenemos como resultado:

{'peras': 50, 'papas': 5}

Podemos conocer en cualquier momento la cantidad de pares clave-valor que contiene nuestro diccionario mediante la función len:

Page 28: Manual Phyton

print len(productos)

Con nuestro problema tenemos como resultado que nuestro diccionario tiene 2 elementos.

Problema resuelto

Crear un diccionario cuyas claves sean palabras en inglés y su valor almacena la palabra traducida al castellano.

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'}

print diccionario['house']print '<br>'print diccionario['red']

Resultado:casa rojo

Problema Propuesto

Crear un diccionario asociando nombres de paises y cantidades de habitantes. Imprimir luego el diccionario.

Ver solución

paises={'argentina':40000000,'españa':46000000,'brasil':190000000}print paises

Formato de cadenas de caracteres (string)

Cuando tenemos que combinar cadenas de caracteres e incorporarle valores almacenados en otras variables el lenguaje Python nos suministra una técnica para incrustar valores dentro de la cadena.

Veamos mediante ejemplos cual es la sintaxis para plantear estos formatos de cadenas:

x1=10x2=5x3=20print 'El contenido de la primer variable es %d, de la segunda %d y la tercera %d' % (x1,x2,x3)

Si bien podemos utilizar el operador + para ir concatenando cadenas y variables esta técnica hace que nuestro programa sea más legible sobre todo cuando tenemos que sustituir varias variables dentro de una cadena.

Primero indicamos entre comillas la cadena y utilizamos el símbolo % para indicar el lugar donde se sustituirá el valor, debemos indicar luego del caracter % el tipo de dato (en nuestro ejemplo un valor decimal (d))

Page 29: Manual Phyton

Luego de la cadena debemos indicar una tupla con los valores o variables de donde se obtendrán los datos. Entre la cadena de formato y la tupla debemos disponer el caracter % (aquí el caracter porcentaje tiene un objetivo distinto que dentro de la cadena de formato)

Se especifican distintos caracteres para cada tipo de dato a sustituir:

x=10g=10.2cadena='juan'print 'El valor entero %d el valor real %f y la cadena %s' % (x,g,cadena)

En el ejemplo propuesto vemos que podemos utilizar los caracteres de formato d (decimal), f (float) y s (string).

Es importante el orden de los valores de la tupla ya que el lenguaje procesa los datos en forma secuencia, es decir cada vez que debe sustituir un valor en la cadena extrae de la tupla el siguiente valor.

Cuando damos formato a una variable real (con coma) podemos disponer dos valores previos al caracter f:

g=20.5498print 'El valor real es %10.2f' % (g)

El primer valor indica el largo total a reservar y el segundo la cantidad de decimales.

Podemos convertir el valor decimal a tipo octal o hexadecimal:

x=255print 'Decimal %d en hexadecimal es %x y en octal %o' % (x,x,x) #Decimal 255 en hexadecimal es ff y en octal 377

No es obligatorio que el formato de cadena se utilice siempre en un print, podemos almacenar el resultado del formato en otra variable string (que podemos eventualmente almacenarla en una base de datos por ejemplo).

vx=10vy=90resultado='(%d,%d)' % (vx,vy)print resultado # (10,90)

También podemos indicar un valor entero en el formato para los tipos de datos enteros y string:

x1=100x2=1500x3=5print '<pre>'print '%5d' % (x1)print '%5d' % (x2)print '%5d' % (x3)print '</pre>'

El resultado por pantalla es:

100 1500 5

Es decir reserva en este caso 5 espacios para el entero y hace la alineación a derecha.

Si indicamos un valor negativo los datos se alínean a izquierda:

Page 30: Manual Phyton

animales=['perro','elefante','pez']print '<pre>'for elemento in animales: print '%20s' % elementofor elemento in animales: print '%-20s' % elementoprint '</pre>'

El resultado de ejecutar el programa es:

perro elefante pezperro elefante pez

Problema resuelto

Imprimir todos los números desde el 1 hasta el 255 en decimal, octal y hexadecimal.

print '<pre>'for num in range(1,256): print '%3d %3o %3x' % (num,num,num)print '</pre>'

Resultado:1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 10 8 9 11 9 10 12 a 11 13 b 12 14 c 13 15 d 14 16 e 15 17 f 16 20 10 17 21 11 18 22 12 19 23 13 20 24 14 21 25 15 22 26 16 23 27 17 24 30 18 25 31 19 26 32 1a 27 33 1b 28 34 1c 29 35 1d 30 36 1e 31 37 1f 32 40 20 33 41 21 34 42 22 35 43 23 36 44 24 37 45 25

Page 31: Manual Phyton

38 46 26 39 47 27 40 50 28 41 51 29 42 52 2a 43 53 2b 44 54 2c 45 55 2d 46 56 2e 47 57 2f 48 60 30 49 61 31 50 62 32 51 63 33 52 64 34 53 65 35 54 66 36 55 67 37 56 70 38 57 71 39 58 72 3a 59 73 3b 60 74 3c 61 75 3d 62 76 3e 63 77 3f 64 100 40 65 101 41 66 102 42 67 103 43 68 104 44 69 105 45 70 106 46 71 107 47 72 110 48 73 111 49 74 112 4a 75 113 4b 76 114 4c 77 115 4d 78 116 4e 79 117 4f 80 120 50 81 121 51 82 122 52 83 123 53 84 124 54 85 125 55 86 126 56 87 127 57 88 130 58 89 131 59 90 132 5a 91 133 5b 92 134 5c 93 135 5d 94 136 5e 95 137 5f 96 140 60 97 141 61 98 142 62 99 143 63100 144 64101 145 65102 146 66103 147 67104 150 68

Page 32: Manual Phyton

105 151 69106 152 6a107 153 6b108 154 6c109 155 6d110 156 6e111 157 6f112 160 70113 161 71114 162 72115 163 73116 164 74117 165 75118 166 76119 167 77120 170 78121 171 79122 172 7a123 173 7b124 174 7c125 175 7d126 176 7e127 177 7f128 200 80129 201 81130 202 82131 203 83132 204 84133 205 85134 206 86135 207 87136 210 88137 211 89138 212 8a139 213 8b140 214 8c141 215 8d142 216 8e143 217 8f144 220 90145 221 91146 222 92147 223 93148 224 94149 225 95150 226 96151 227 97152 230 98153 231 99154 232 9a155 233 9b156 234 9c157 235 9d158 236 9e159 237 9f160 240 a0161 241 a1162 242 a2163 243 a3164 244 a4165 245 a5166 246 a6167 247 a7168 250 a8169 251 a9170 252 aa171 253 ab

Page 33: Manual Phyton

172 254 ac173 255 ad174 256 ae175 257 af176 260 b0177 261 b1178 262 b2179 263 b3180 264 b4181 265 b5182 266 b6183 267 b7184 270 b8185 271 b9186 272 ba187 273 bb188 274 bc189 275 bd190 276 be191 277 bf192 300 c0193 301 c1194 302 c2195 303 c3196 304 c4197 305 c5198 306 c6199 307 c7200 310 c8201 311 c9202 312 ca203 313 cb204 314 cc205 315 cd206 316 ce207 317 cf208 320 d0209 321 d1210 322 d2211 323 d3212 324 d4213 325 d5214 326 d6215 327 d7216 330 d8217 331 d9218 332 da219 333 db220 334 dc221 335 dd222 336 de223 337 df224 340 e0225 341 e1226 342 e2227 343 e3228 344 e4229 345 e5230 346 e6231 347 e7232 350 e8233 351 e9234 352 ea235 353 eb236 354 ec237 355 ed238 356 ee

Page 34: Manual Phyton

239 357 ef240 360 f0241 361 f1242 362 f2243 363 f3244 364 f4245 365 f5246 366 f6247 367 f7248 370 f8249 371 f9250 372 fa251 373 fb252 374 fc253 375 fd254 376 fe255 377 ff

Problema Propuesto

Almacenar en una lista los nombres de personas y en otra los sueldos que cobran cada uno. Hacer que para el índice cero de cada componente representen los datos de una persona y así sucesivamente.

Imprimir un nombre por línea de la pantalla y hacer que los sueldos aparezcan correctamente alineados las columnas de unidades, decenas, centenas etc.

Ver solución

nombres=['juan','ana','luis']sueldos=[1500.55,2700.00,910.66]

print '<pre>'for indice in range(0,len(nombres)): print '%-20s %10.2f' % (nombres[indice],sueldos[indice])print '</pre>'

Asignaciones múltiples

Python permite asignaciones múltiples:

x1,x2,x3=1,2,3print x1 # 1print x2 # 2print x3 # 3

Para entenderlo mejor podemos también utilizar esta sintaxis:

x1,x2,x3=(1,2,3)print x1 # 1print x2 # 2print x3 # 3

Es decir lo que estamos haciendo inicializar cada una de las variables de la izquierda con las componentes homólogas (de la misma posición) de la tupla.

Esta característica es útil si tenemos que recuperar por ejemplo de una lista que contiene tuplas de dos elementos que representan puntos en el plano (x,y):

Page 35: Manual Phyton

puntos=[(10,2),(4,2),(9,3)]for x,y in puntos: print 'Coordenada x:%d y:%d' % (x,y) print '<br>'

Cada vuelta del for se almacena en x e y los valores de la tupla a procesar.

Otra aplicación muy útil es si queremos intercambiar el valor de dos variables la forma más simple es:

x=10y=20print x # 10print y # 20x,y = y,xprint x # 20print y # 10

En una asignación pueden intervenir valores de distinto tipo (enteros, reales, string etc.):

nombre,edad,sueldo=('juan',32,1500.30)print 'Nombre:%s Edad:%d Sueldo%10.2f' % (nombre,edad,sueldo) # Nombre:juan Edad:32 Sueldo 1500.30

Podemos con esto hacer que una función retorne más de un dato (por lo menos en apariencia), esto lo logramos retornando una tupla:

def sumadiferencia(x1,x2): suma=x1+x2 diferencia=x1-x2 return (suma,diferencia)

su,di=sumadiferencia(10,4)print su # 14print di # 6

Como vemos llamamos a una función y le asignamos el valor devuelto a dos variables.

Si queremos inicializar tres variables con el mismo valor la sintaxis que podemos utilizar es:

x1=x2=x3=10print x1 # 10print x2 # 10print x3 # 10

Problema resuelto

En una lista se almacenan tuplas con el nombre de una persona y su edad. Mostrar el nombre de la persona de mayor edad.

personas=[('juan',22),('ana',40),('carlos',15)]

may=-1for nombre,edad in personas: if edad>may: nom=nombre may=edadprint '%s tiene la edad mayor y es de %d' % (nom,may)

Resultado:

Page 36: Manual Phyton

ana tiene la edad mayor y es de 40

Funciones con parámetros por defecto

Como habíamos visto una función es una estructura de programación que agrupa un conjunto de instrucciones y resuelve un problema particular. Una función puede tener parámetros, los mismos almacenan los valores que se le pasan cuando la llamamos.

En algunos casos si queremos que la función sea mas flexible podemos definir parámetros con valores por defecto. Esto nos permite llamar a la función pudiendo o no pasar datos a dichos parámetros.

Veamos con un ejemplo este concepto, vamos a desarrollar una función que reciba un dato a imprimir, con la posibilidad de indicarle el color de fuente y el color de fondo, en caso de no indicarle dichos valores la función muestra el dato con color negro y fondo blanco.

def mostrartitulo(dato,colorletra='#000',colorfondo='#fff'): print '<h1 style="color:'+colorletra+';background-color:'+colorfondo+'">'+dato+'</h1>'

mostrartitulo('Primer titulo')mostrartitulo('Segundo titulo','#f00')mostrartitulo('Tercer titulo','#f00','#000')

Como podemos ver para indicar a Python que un parámetro es por defecto debemos utilizar el operador de asignación en la declaración de la cabecera de la función junto al valor que tomará dicho parámetro en caso de no pasarlo desde donde la llamamos:

def mostrartitulo(dato,colorletra='#000',colorfondo='#fff'):

Cuando llamamos la función mostrartitulo podemos hacerlo de diferentes maneras:

mostrartitulo('Primer titulo')mostrartitulo('Segundo titulo','#f00')mostrartitulo('Tercer titulo','#f00','#000')

La primer llamada es pasando un único dato, es decir solo el título que debe mostrar, en este caso el segundo y tercer parámetro toman como valor el indicado en el declaración:

colorletra='#000',colorfondo='#fff'

Podemos llamar a la función mostrartitulo pasando el primer parámetro y el segundo, lo que hace que el tercer parámetro se inicialice con el indicado en la declaración de la función:

mostrartitulo('Segundo titulo','#f00')

En el ejemplo la tercer llamada a la función se hace pasando tres parámetros:

mostrartitulo('Tercer titulo','#f00','#000')

Como podemos ver los parámetros por defecto nos permiten implementar funciones más generales, con esto podemos hacer que las funciones sean útiles para mayor cantidad de situaciones.

Que pasa si queremos llamar la función indicando el primer y último parámetro, esto solo se puede hacer si al llamar la función indicamos que dato se le pasa a cada parámetro:

def mostrartitulo(dato,colorletra='#000',colorfondo='#fff'):

Page 37: Manual Phyton

print '<h1 style="color:'+colorletra+';background-color:'+colorfondo+'">'+dato+'</h1>'

mostrartitulo(dato='Primer titulo',colorfondo='#00f')

Si bien se hace más engorroso la llamada a la función al tener que indicar el nombre de cada parámetro junto al valor, nos trae como beneficio que sea aún más flexible.

Problema resuelto

Confeccionar una función que reciba un dato a imprimir, con la posibilidad de indicarle el color de fuente y el color de fondo, en caso de no indicarle dichos valores la función muestra el dato con color negro y fondo blanco.

def mostrartitulo(dato,colorletra='#000',colorfondo='#fff'): print '<h1 style="color:'+colorletra+';background-color:'+colorfondo+'">'+dato+'</h1>'

mostrartitulo('Primer titulo')mostrartitulo('Segundo titulo','#f00')mostrartitulo('Tercer titulo','#f00','#000')

Resultado:

Primer titulo

Segundo titulo

Tercer titulo

Problema Propuesto

Confeccionar una función que reciba entre 2 y 5 enteros. La misma nos debe retornar la suma de dichos valores.

Ver solución

def sumar(v1,v2,v3=0,v4=0,v5=0): s=v1+v2+v3+v4+v5 return s

print sumar(5,6)print '<br>'print sumar(1,2,3)print '<br>'x=sumar(1,2,3,4,5)print x

Page 38: Manual Phyton

Funciones con una cantidad variable de parámetros

Otra posibilidad en la declaración de una función en Python es la definición de una cantidad variable de parámetros.

Para definir una cantidad variante de parámetros debemos antecederle el caracter asterísco (*) al último parámetro de la función.

Supongamos que necesitemos implementar una función que le enviemos una serie de enteros y nos retorne la suma de todos ellos (como mínimo le enviamos 2 y no hay un máximo de valores):

def sumar(x1,x2,*xn): s=x1+x2 for valor in xn: s=s+valor return s

print sumar(1,2)print '<br>'print sumar(1,2,3,4)print '<br>'print sumar(1,2,3,4,5,6,7,8,9,10)

Lo que en realidad el lenguaje Python hace es una tupla con todos los valores de los parámetros a partir del tercero.

Luego nuestro algoritmo debe recorrer la tupla para procesar los elementos propiamente dichos, en nuestro caso con un for in y los sumamos junto al primer y segundo parámetro.

Luego cuando hacemos la llamada a la función:

print sumar(1,2)

Si pasamos solo dos parámetros la tupla se inicializa vacía, por lo que el for in no ejecuta el bloque contenido.

Si llamamos la función con 10 parámetros:

print sumar(1,2,3,4,5,6,7,8,9,10)

Luego la tupla se crea con 7 elementos.

Problema resuelto

Implementar una función que le enviemos una serie de enteros y nos retorne la suma de todos ellos (como mínimo le enviamos 2 y no hay un máximo de valores):

def sumar(x1,x2,*xn): s=x1+x2 for valor in xn: s=s+valor return s

print sumar(1,2)print '<br>'print sumar(1,2,3,4)

Page 39: Manual Phyton

print '<br>'print sumar(1,2,3,4,5,6,7,8,9,10)

Resultado:3 10 55

Problema Propuesto

Confeccionar una función que le envíe una serie de edades y me retorne la cantidad que son mayores a 18 (como mínimo se envía un entero a la función)

Ver solución

def cantidadmayor18(ed1,*edades): cant=0 if ed1>18: cant=cant+1 for e in edades: if e>18: cant=cant+1 return cant

print 'Cantidad de personas mayores a 18:'cant=cantidadmayor18(4,56,14,67,32,21)print cant

Implementación de módulos

Cuando uno codifica un programa en Python lo almacena en un archivo con extensión *.py

Una vez instalado el Python en forma local podemos llamar un programa desde la línea de comando del sistema operativo.

Si tenemos un programa mínimo llamado: programa1.py

def holamundo(): print('Hola Mundo')

holamundo();

Luego desde la carpeta donde hemos instalado el Python debemos ejecutarlo con la siguiente sintaxis:

c:\Python25>python c:\pruebaspython\programa1.py

Luego de esto veremos en pantalla el mensaje 'Hola Mundo'

Este archivo en Python se lo llama módulo.

Un programa pequeño puede estar formado por un único módulo, pero programas de mayor tamaño deben dividirse en distintos módulos para facilitar su mantenimiento. Cada módulo normalmente almacena un conjunto de funciones relacionadas.

Page 40: Manual Phyton

La sintaxis para llamar a una función que se encuentra en otro módulo es la siguiente:

modulo1.py

def funcion1(): print 'Función 1'

modulo2.py

import modulo1

def funcion2(): modulo1.funcion1() print 'Función 2'

funcion2()

Luego desde la línea de comandos ejecutamos el modulo2.py:

c:\Python25>python c:\pruebaspython\modulo2.py

Y como resultado tenemos en pantalla

Función 1Función 2

Veremos más adelante que Python nos provee de una gran biblioteca de módulos. Recordemos que ya hemos estado utilizando la función randint que se encuentra en el módulo random:

import random

x=random.randint(1,1000)print x

Funciones de uso común (range - type - str - dir)

Como hemos visto en el punto anterior Python agrupa las funciones en módulos que serán importados en el caso que nuestro programa los necesite. Pero hay un pequeño grupo de funciones que Python las importa de forma automática, esto quiere decir que podemos hacer uso sin tener que hacer un import.

Funciones incorporadas en Python

range([inicio],fin,[paso])La función range devuelve una lista de valores enteros, comienza con el valor pasado al parámetro [inicio], en caso de omitir este parámetro comienza en cero y finaliza con el valor indicado en el parámetro 'fin' sin incluirlo. En caso de indicar el parámetro [paso] la lista de valores crece según dicho número, sino se incrementa de a uno.

lista1=range(5,10) print lista1 # [5, 6, 7, 8, 9] lista2=range(10) print lista2 # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] lista3=range(-5,5) print lista3 # [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] lista4=range(1,10,3) print lista4 # [1, 4, 7]

Page 41: Manual Phyton

Es muy común utilizar esta función para generar un contador con la estructura for in, por ejemplo si queremos mostrar los números del 1 al 10:

for x in range(1,11): print x print '-'

str(variable)Convierte el contenido del parámetro a cadena y lo retorna. Funciona para cualquier tipo de dato como puede ser un entero, real, tupla, lista etc.Muy útil cuando tenemos que generar un string a partir de un conjunto de variables heterogeneas.

x=10 y=2.5 fin=False edades=(40,50) print str(x) + str(y) + str(fin) + str(edades)

En el ejemplo concatenamos el contenido de cuatro variables de distinto tipo, para ello debemos llevarlas a todas a tipo string.

type(variable)Retorna el tipo de una variable.

x=10 print type(x) # <type 'int'> y=2.5 print type(y) # <type 'float'> fin=False print type(fin) # <type 'bool'> edades=(40,50) print type(edades) # <type 'tuple'>

dir(variable)Si pasamos como parámetro a la función dir un objeto luego nos devuelve todos los métodos que tiene definidos la clase de dicho objeto (veremos más adelante en profundidad cada uno de los métodos de la clase lista y diccionario):

lista1=[2,4,6] print dir(lista1) #['__add__', '__class__', '__contains__', '__delattr__', # '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', # '__getattribute__', '__getitem__', '__getslice__', '__gt__', # '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', # '__le__', '__len__', '__lt__', '__mul__', '__ne__',

'__new__', # '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', # '__rmul__', '__setattr__', '__setitem__', '__setslice__', # '__str__', 'append', 'count', 'extend', 'index', 'insert', # 'pop', 'remove', 'reverse', 'sort'] dic1={'juan':44,'ana':3} print dir(dic1) # ['__class__', '__cmp__', '__contains__', '__delattr__',

'__delitem__', # '__doc__', '__eq__', '__ge__', '__getattribute__',

'__getitem__', '__gt__', # '__hash__', '__init__', '__iter__', '__le__', '__len__',

'__lt__', '__ne__', # '__new__', '__reduce__', '__reduce_ex__', '__repr__',

'__setattr__', '__setitem__', # '__str__', 'clear', 'copy', 'fromkeys', 'get', 'has_key',

'items', 'iteritems', # 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem',

'setdefault', 'update', 'values']

Page 42: Manual Phyton

Si le pasamos como parámetro el nombre de un módulo la función dir nos retorna todas las funciones definidas entre otros datos (recordemos que hemos estado utilizando la función randint para generar un valor aleatorio y como podemos ver se encuentra listado al llamar a la función dir):

import random

print dir(random) # ['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', # 'SystemRandom', 'TWOPI', 'WichmannHill', '_BuiltinMethodType', '_MethodType', # '__all__', '__builtins__', '__doc__', '__file__', '__name__', '_acos', '_ceil', # '_cos', '_e', '_exp', '_hexlify', '_inst', '_log', '_pi', '_random', '_sin', # '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betavariate', # 'choice', 'expovariate', 'gammavariate', 'gauss', 'getrandbits', 'getstate', # 'jumpahead', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', # 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle', 'uniform', # 'vonmisesvariate', 'weibullvariate']

Problema resuelto

Mediante la función dir obtener el contenido del módulo zlib.

import zlib

print dir(zlib)

Problema Propuesto

Mostrar la tabla de multiplicar 5 (desde el 5 al 50), emplear la función range

Ver solución

for valor in range(5,55,5): print str(valor)+'-'

Función de uso común (help)

La función help tiene por objetivo ayudar al programador dando información de documentación definidas en módulos, funciones, clases etc.

Veamos que nos devuelve la función help si le pasamos como parámetro la función randint:

import random

help(random.randint) # Help on method randint in module random: randint(self, a, b) # method of random.Random instance Return random integer in # range [a, b], including both end points.

Podemos observar que nos informa el módulo donde se almacena, sus parámetros y el objetivo de la misma.

Page 43: Manual Phyton

Nosotros podemos crear cadenas de documentación para nuestras funciones con la siguiente sintaxis:

def sumar(v1,v2): """El objetivo de esta funcion es realizar la suma de los dos valores que recibe como parametro y retornarlo.""" su=v1+v2 return su

help(sumar) # Help on function sumar in module __main__: sumar(v1, v2) # El objetivo de esta funcion es realizar la suma de los # dos valores que recibe como parametro y retornarlo.

El string que definamos inmediatamente después de la cabecera se tomará como cadena de documentación de la función. Como en este caso nuestra cadena de documentación ocupa varias líneas en Python podemos encerrarla entre triples comillas y no deberemos indicar el caracter de continuación de línea (Si la cadena de documentación es una sola línea podemos emplear una sola comillas al principio y al final)

Si utilizamos una sola comillas debemos indicar al final de cada línea que continúa:

def sumar(v1,v2): "El objetivo de esta funcion es realizar la \ suma de los dos valores que recibe como \ parametro y retornarlo." su=v1+v2 return su

Podemos crear cadenas de documentación para definir objetivos del mismo.

Si tenemos un módulo mínimo llamado: modulo1.py, podemos definir las siguientes cadenas de documentación

"cadena de documentacion del modulo"

def holamundo(): "cadena de documentacion de funcion" print('Hola Mundo')

Problema resuelto

Llamar la función help para mostrar las cadenas de documentación del módulo random, de la función randint, de una variable de tipo entera y de una variable de tipo lista.

import random

help(random)print '<hr>'help(random.randint)print '<hr>'x=4help(x)print '<hr>'lista1=[1,2,3];help(lista1)

Resultado:Help on module random: NAME random - Random variable generators. FILE /base/python_runtime/python_dist/lib/python2.5/random.py MODULE DOCS

Page 44: Manual Phyton

http://www.python.org/doc/current/lib/module-random.html DESCRIPTION integers -------- uniform within range sequences --------- pick random element pick random sample generate random permutation distributions on the real line: ------------------------------ uniform normal (Gaussian) lognormal negative exponential gamma beta pareto Weibull distributions on the circle (angles 0 to 2pi) --------------------------------------------- circular uniform von Mises General notes on the underlying Mersenne Twister core generator: * The period is 2**19937-1. * It is one of the most extensively tested generators in existence. * Without a direct way to compute N steps forward, the semantics of jumpahead(n) are weakened to simply jump to another distant state and rely on the large period to avoid overlapping sequences. * The random() method is implemented in C, executes in a single Python step, and is, therefore, threadsafe. CLASSES _random.Random(__builtin__.object) Random SystemRandom WichmannHill class Random(_random.Random) | Random number generator base class used by bound module functions. | | Used to instantiate instances of Random to get generators that don't | share state. Especially useful for multi-threaded programs, creating | a different instance of Random for each thread, and using the jumpahead() | method to ensure that the generated sequences seen by each thread don't | overlap. | | Class Random can also be subclassed if you want to use a different basic | generator of your own devising: in that case, override the following | methods: random(),

Conceptos de programación orientada a objetos

Habíamos dicho que Python nos permite combinar las metodologías de programación Lineal, Estructurada y Orientada a Objetos. A partir de este concepto mostraremos en forma sencilla la metodología de Programación Orientada a Objetos.

Se irán introduciendo conceptos de objeto, clase, atributo, método etc. y de todos estos temas se irán planteando problemas resueltos.

Prácticamente todos los lenguajes desarrollados en los últimos 15 años implementan la posibilidad de trabajar con POO (Programación Orientada a Objetos)

El lenguaje Python tiene la característica de permitir programar con las siguientes metodologías:

Programación Lineal: Es cuando desarrollamos todo el código sin emplear funciones. Programación Estructurada: Es cuando planteamos funciones que agrupan actividades a desarrollar y

luego dentro del programa llamamos a dichas funciones que pueden estar dentro del mismo archivo o en una librería separada.

Programación Orientada a Objetos: Es cuando planteamos clases y definimos objetos de las mismas (Este es el objetivo de los próximos conceptos, aprender la metodología de programación orientada a objetos y la sintaxis particular de Python para la POO)

Conceptos básicos de Objetos

Un objeto es una entidad independiente con sus propios datos y programación. Las ventanas, menúes, carpetas de archivos pueden ser identificados como objetos; el motor de un auto también es considerado un objeto, en este caso, sus datos (atributos) describen sus características físicas y su programación (métodos) describen el funcionamiento interno y su interrelación con otras partes del automóvil (también objetos).

El concepto renovador de la tecnología Orientación a Objetos es la suma de funciones a elementos de datos, a esta unión se le llama encapsulamiento. Por ejemplo, un objeto página contiene las dimensiones físicas de la página (ancho, alto), el color, el estilo del borde, etc, llamados atributos. Encapsulados con estos datos se encuentran los métodos para modificar el tamaño de la página, cambiar el color, mostrar texto, etc. La responsabilidad de un objeto pagina consiste en realizar las acciones apropiadas y mantener actualizados sus datos internos. Cuando otra parte del programa (otros objetos) necesitan que la pagina realice alguna de estas tareas (por ejemplo, cambiar de color) le envía un mensaje. A estos objetos que envían mensajes no les

Page 45: Manual Phyton

interesa la manera en que el objeto página lleva a cabo sus tareas ni las estructuras de datos que maneja, por ello, están ocultos. Entonces, un objeto contiene información pública, lo que necesitan los otros objetos para interactuar con él e información privada, interna, lo que necesita el objeto para operar y que es irrelevante para los otros objetos de la aplicación.

Declaración de una clase y creación de objetos

La programación orientada a objetos se basa en la programación de clases; a diferencia de la programación estructurada, que está centrada en las funciones.

Una clase es un molde del que luego se pueden crear múltiples objetos, con similares características.

Un poco más abajo se define una clase Persona y luego se crean dos objetos de dicha clase.

Una clase es una plantilla (molde), que define atributos (lo que conocemos como variables) y métodos (lo que conocemos como funciones).

La clase define los atributos y métodos comunes a los objetos de ese tipo, pero luego, cada objeto tendrá sus propios valores y compartirán las mismas funciones.

Debemos crear una clase antes de poder crear objetos (instancias) de esa clase. Al crear un objeto de una clase, se dice que se crea una instancia de la clase o un objeto propiamente dicho.

Confeccionaremos nuestra primer clase para conocer la sintaxis en el lenguaje Python, luego definiremos dos objetos de dicha clase.

Implementaremos una clase llamada Persona que tendrá como atributo (variable) su nombre y dos métodos (funciones), uno de dichos métodos inicializará el atributo nombre y el siguiente método mostrará en la página el contenido del mismo.

class Persona: def inicializar(self,nom): self.nombre=nom

def imprimir(self): print 'Nombre:' print self.nombre print '<br>'

persona1=Persona()persona1.inicializar('Juan')persona1.imprimir()

persona2=Persona()persona2.inicializar('Ana')persona2.imprimir()

Siempre conviene buscar un nombre de clase lo más próximo a lo que representa. La palabra clave para declarar la clase es class, seguidamente el nombre de la clase y luego dos puntos.

Los métodos de una clase se definen utilizando la misma sintaxis que para la definición de funciones.

Como veremos todo método tiene como primer parámetro el identificador self que tiene la referencia del objeto que llamó al método.

Luego dentro del método diferenciamos los atributos del objeto antecediendo el identificador self:

Page 46: Manual Phyton

self.nombre=nom

Con la asignación previa almacenamos en el atributo nombre el parámetro nom, los atributos siguen existiendo cuando finaliza la ejecución del método. Por ello cuando se ejecuta el método imprimir podemos mostrar el nombre que cargamos en el primer método.

Decíamos que una clase es un molde que nos permite definir objetos. Ahora veamos cual es la sintaxis para la definición de objetos de la clase Persona:

persona1=Persona()persona1.inicializar('Juan')persona1.imprimir()

Definimos un objeto llamado persona1 y lo creamos asignándole el nombre de la clase.

Luego para llamar a los métodos debemos anteceder el nombre del objeto el operador . y por último el nombre del método.

En el caso que tenga parámetros se los enviamos (salvo el primer parámetro (self) que el mismo Python se encarga de enviar la referencia del objeto que se creó):

persona1.inicializar('Juan')

También podemos definir tantos objetos de la clase Persona como sean necesarios para nuestro algoritmo:

persona2=Persona()persona2.inicializar('Ana')persona2.imprimir()

Esto nos da una idea que si en una página WEB tenemos 2 menúes, seguramente definiremos una clase Menu y luego crearemos dos objetos de dicha clase.

Esto es una de las ventajas fundamentales de la Programación Orientada a Objetos (POO), es decir reutilización de código (gracias a que está encapsulada en clases) es muy sencilla.

Problema resuelto

Confeccionar una clase llamada Persona. Definir un atributo donde se almacene su nombre. Luego definir dos métodos, uno que cargue el nombre y otro que lo imprima.

class Persona: def inicializar(self,nom): self.nombre=nom

def imprimir(self): print 'Nombre:' print self.nombre print '<br>'

persona1=Persona()persona1.inicializar('Juan')persona1.imprimir()

persona2=Persona()persona2.inicializar('Ana')persona2.imprimir()

Page 47: Manual Phyton

Resultado:Nombre: Juan Nombre: Ana

Problema Propuesto

Confeccionar una clase Empleado, definir como atributos su nombre y sueldo.Definir un método inicializar que lleguen como dato el nombre y sueldo. Plantear un segundo método que imprima el nombre, sueldo y un mensaje si debe o no pagar impuestos (si el sueldo supera a 3000 paga impuestos)

Ver soluciónclass Empleado: def inicializar(self,nom,suel): self.nombre=nom self.sueldo=suel def pagaimpuestos(self): print 'Nombre:' print self.nombre print '<br>' print 'Sueldo:' print self.sueldo print '<br>' if self.sueldo>300: print 'Debe pagar impuestos'

emp1=Empleado()emp1.inicializar('Juan',3500)emp1.pagaimpuestos()

Atributos de una clase

Ahora trataremos de concentrarnos en los atributos de una clase. Los atributos son las características, cualidades, propiedades distintivas de cada clase. Contienen información sobre el objeto. Determinan la apariencia, estado y demás particularidades de la clase. Varios objetos de una misma clase tendrán los mismos atributos pero con valores diferentes.

Cuando creamos un objeto de una clase determinada, los atributos declarados por la clase son localizadas en memoria y pueden ser modificados mediante los métodos.

Plantearemos un nuevo problema para analizar detenidamente la definición, sintaxis y acceso a los atributos.

Problema: Implementar una clase que muestre una lista de hipervínculos en forma horizontal (básicamente un menú de opciones)

Lo primero que debemos pensar es que valores almacenará la clase, en este caso debemos cargar una lista de direcciones web y los títulos de los enlaces. Podemos definir dos listas paralelas que almacenen las direcciones y los títulos respectivamente.

Definiremos dos métodos: cargaropcion y mostrar.

Page 48: Manual Phyton

class Menu: enlaces=[] titulos=[] def cargaropcion(self,en,tit): self.enlaces.append(en) self.titulos.append(tit)

def mostrar(self): for indice in range(0,len(self.enlaces)): print '<a href="'+self.enlaces[indice]+'">'+self.titulos[indice]+'</a>'

menu1=Menu()menu1.cargaropcion('http://www.google.com.ar','Google')menu1.cargaropcion('http://www.yahoo.com.ar','Yahoo')menu1.cargaropcion('http://www.live.com.ar','Msn')menu1.mostrar()

En este caso los atributos son de tipo listas y estamos obligados a definirlos dentro de la clase y previo a la declaración de los métodos:

enlaces=[] titulos=[]

Estamos definiendo dos listas vacías.

El método cargaropcion recibe el enlace y el título y los almacena al final de cada lista empleando el método append de la lista (tengamos en cuenta que Python administra las listas como objetos)

self.enlaces.append(en) self.titulos.append(tit)

El método que imprime todos los enlaces utiliza un for para recorrer las listas y acceder a cada elemento de las listas y mostrarlos dentro de la página:

for indice in range(0,len(self.enlaces)): print '<a href="'+self.enlaces[indice]+'">'+self.titulos[indice]+'</a>'

Luego creamos un objeto de la clase Menu y llamamos tantas veces al método cargaropcion como opciones tenga nuestro menú:

menu1=Menu()menu1.cargaropcion('http://www.google.com.ar','Google')menu1.cargaropcion('http://www.yahoo.com.ar','Yahoo')menu1.cargaropcion('http://www.live.com.ar','Msn')

Finalmente llamamos al método mostrar que imprime cada hipervínculo en la página:

menu1.mostrar()

Problema resuelto

Implementar una clase que muestre una lista de hipervínculos en forma horizontal (básicamente un menú de opciones)

class Menu: enlaces=[] titulos=[] def cargaropcion(self,en,tit): self.enlaces.append(en)

Page 49: Manual Phyton

self.titulos.append(tit)

def mostrar(self): for indice in range(0,len(self.enlaces)): print '<a href="'+self.enlaces[indice]+'">'+self.titulos[indice]+'</a>'

menu1=Menu()menu1.cargaropcion('http://www.google.com.ar','Google')menu1.cargaropcion('http://www.yahoo.com.ar','Yahoo')menu1.cargaropcion('http://www.live.com.ar','Msn')menu1.mostrar() Resultado:Google Yahoo Msn

Problema Propuesto

Confeccionar una clase Menu. Permitir añadir la cantidad de opciones que necesitemos. Mostrar el menú en forma horizontal o vertical (según que método llamemos)

Ver soluciónclass Menu: enlaces=[] titulos=[] def cargaropcion(self,en,tit): self.enlaces.append(en) self.titulos.append(tit)

def mostrarhorizontal(self): for indice in range(0,len(self.enlaces)): print '<a href="'+self.enlaces[indice]+'">'+self.titulos[indice]+'</a>'

def mostrarvertical(self): for indice in range(0,len(self.enlaces)): print '<a href="'+self.enlaces[indice]+'">'+self.titulos[indice]+'</a><br>'

menu1=Menu()menu1.cargaropcion('http://www.google.com.ar','Google')menu1.cargaropcion('http://www.yahoo.com.ar','Yahoo')menu1.cargaropcion('http://www.live.com.ar','Msn')menu1.mostrarvertical()

Metodos de una clase

Los métodos son como las funciones en los lenguajes estructurados, pero están definidos dentro de una clase y operan sobre los atributos de dicha clase.

Los métodos también son llamados las responsabilidades de la clase. Para encontrar las responsabilidades de una clase hay que preguntarse qué puede hacer la clase.

El objetivo de un método es ejecutar las actividades que tiene encomendada la clase a la cual pertenece.

Los atributos de un objeto se modifican mediante llamadas a sus métodos.

Page 50: Manual Phyton

Confeccionaremos un nuevo problema para concentrarnos en la definición y llamada a métodos.Problema:Confeccionar una clase CabeceraPagina que permita mostrar un título, indicarle si queremos que aparezca centrado, a derecha o izquierda.

Definiremos dos atributos, uno donde almacenar el título y otro donde almacenar la ubicación.

Ahora pensemos que métodos o responsabilidades debe tener esta clase para poder mostrar la cabecera de la página. Seguramente deberá tener un método que pueda inicializar los atributos y otro método que muestre la cabecera dentro de la página.

Veamos el código de la clase CabeceraPagina

class CabeceraPagina: def inicializar(self,tit,ubi): self.titulo=tit self.ubicacion=ubi

def graficar(self): print '<div style="font-size:40px;text-align:'+self.ubicacion+'">' print self.titulo print '</div>'

cabecera=CabeceraPagina()cabecera.inicializar('El blog del programador','center')cabecera.graficar()

La clase CabeceraPagina tiene dos atributos donde almacenamos el texto que debe mostrar y la ubicación del mismo ('center', 'left' o 'right'), nos valemos de CSS para ubicar el texto en la página.

No es obligatorio en Python definir previo a los métodos todos los atributos. Como vemos se definen e inicializan al llamar al método inicializar.

Ahora analicemos lo que más nos importa en el concepto que estamos concentrados (métodos de una clase):

def inicializar(self,tit,ubi): self.titulo=tit self.ubicacion=ubi

Un método tiene un nombre, conviene utilizar verbos para la definición de métodos (mostrar, inicializar, graficar etc.) y sustantivos para la definición de atributos (color, enlace, titulo etc.)

Un método debe tener como primer parámetro el identificador self, el mismo nos permite acceder a los atributos de la clase, además puede tener otros parámetros que inicializan atributos del objeto:

self.titulo=tit self.ubicacion=ubi

Luego para llamar a los métodos debemos crear un objeto de dicha clase:

cabecera=CabeceraPagina()cabecera.inicializar('El blog del programador','center')cabecera.graficar()

Es importante notar que siempre que llamamos a un método le antecedemos el nombre del objeto. El orden de llamada a los métodos es importante, no va a funcionar si primero llamamos a graficar y luego llamamos al método inicializar.

Page 51: Manual Phyton

Problema resuelto

p>Confeccionar una clase CabeceraPagina que permita mostrar un título, indicarle si queremos que aparezca centrado, a derecha o izquierda.class CabeceraPagina: def inicializar(self,tit,ubi): self.titulo=tit self.ubicacion=ubi

def graficar(self): print '<div style="font-size:40px;text-align:'+self.ubicacion+'">' print self.titulo print '</div>'

cabecera=CabeceraPagina()cabecera.inicializar('El blog del programador','center')cabecera.graficar()

Resultado:

El blog del programador

Problema Propuesto

Confeccionar una clase CabeceraPagina que permita mostrar un título, indicarle si queremos que aparezca centrado, a derecha o izquierda, además permitir definir el color de fondo y de la fuente.

Ver solución

class CabeceraPagina: def inicializar(self,tit,ubi,colfondo,colfuente): self.titulo=tit self.ubicacion=ubi self.colorfondo=colfondo self.colorfuente=colfuente

def graficar(self): print '<div style="font-size:40px;text-align:'+self.ubicacion+';background-color:'+self.colorfondo+';color:'+self.colorfuente+'">' print self.titulo print '</div>'

cabecera=CabeceraPagina()cabecera.inicializar('El blog del programador','center','#FF1A00','#CDEB8B')cabecera.graficar()

Metodo constructor de una clase

El constructor es un método especial de una clase. El objetivo fundamental del constructor es inicializar los atributos del objeto que creamos.

Page 52: Manual Phyton

Básicamente el constructor remplaza al método inicializar que habíamos hecho en el concepto anterior.

Las ventajas de implementar un constructor en lugar del método inicializar son:

1. El constructor es el primer método que se ejecuta cuando se crea un objeto. 2. El constructor se llama automáticamente. Es decir es imposible de olvidarse de llamarlo ya que se

llamará automáticamente. 3. Quien utiliza POO (Programación Orientada a Objetos) conoce el objetivo de este método.

Otras características de los constructores son:

El constructor se ejecuta inmediatamente luego de crear un objeto y no puede ser llamado nuevamente.

Un constructor no puede retornar dato. Un constructor puede recibir parámetros que se utilizan normalmente para inicializar atributos. El constructor es un método opcional, de todos modos es muy común definirlo.

Veamos la sintaxis del constructor:

def __init__([parámetros]): [algoritmo]

Debemos definir un método llamado __init__ (es decir utilizamos dos caracteres de subrayado, la palabra init y seguidamente otros dos caracteres de subrayado).

Confeccionaremos el mismo problema del concepto anterior para ver el cambio que debemos hacer de ahora en más.

Problema:Confeccionar una clase CabeceraPagina que permita mostrar un título, indicarle si queremos que aparezca centrado, a derecha o izquierda.

class CabeceraPagina: def __init__(self,tit,ubi): self.titulo=tit self.ubicacion=ubi

def graficar(self): print '<div style="font-size:40px;text-align:'+self.ubicacion+'">' print self.titulo print '</div>'

cabecera=CabeceraPagina('El blog del programador','center')cabecera.graficar()

Ahora podemos ver como cambió la sintaxis para la definición del constructor:

def __init__(self,tit,ubi): self.titulo=tit self.ubicacion=ubi

Veamos como se modifica la llamada al constructor cuando se crea un objeto:

cabecera=CabeceraPagina('El blog del programador','center')cabecera.graficar()

Es decir el constructor se llama en la misma línea donde creamos el objeto, por eso disponemos después del nombre de la clase los parámetros:

Page 53: Manual Phyton

cabecera=CabeceraPagina('El blog del programador','center')

Generalmente todo aquello que es de vital importancia para el funcionamiento inicial del objeto se lo pasamos mediante el constructor.

Problema resuelto

Confeccionar una clase CabeceraPagina que permita mostrar un título, indicarle si queremos que aparezca centrada, a derecha o izquierda. Utilizar un constructor para inicializar los dos atributos.

class CabeceraPagina: def __init__(self,tit,ubi): self.titulo=tit self.ubicacion=ubi

def graficar(self): print '<div style="font-size:40px;text-align:'+self.ubicacion+'">' print self.titulo print '</div>'

cabecera=CabeceraPagina('El blog del programador','center')cabecera.graficar()

Resultado:El blog del programador

Problema Propuesto

Confeccionar una clase CabeceraPagina que permita mostrar un título, indicarle si queremos que aparezca centrado, a derecha o izquierda, además permitir definir el color de fondo y de la fuente. Pasar los valores que cargaran los atributos mediante un constructor.

Ver soluciónclass CabeceraPagina: def __init__(self,tit,ubi,colfondo,colfuente): self.titulo=tit self.ubicacion=ubi self.colorfondo=colfondo self.colorfuente=colfuente

def graficar(self): print '<div style="font-size:40px;text-align:'+self.ubicacion+';background-color:'+self.colorfondo+';color:'+self.colorfuente+'">' print self.titulo print '</div>'

cabecera=CabeceraPagina('El blog del programador','center','#FF1A00','#CDEB8B')cabecera.graficar()

Page 54: Manual Phyton

Llamada de métodos dentro de la clase

Hasta ahora todos los problemas planteados hemos llamado a los métodos desde donde definimos un objeto de dicha clase, por ejemplo:

cabecera=CabeceraPagina('El blog del programador','center')cabecera.graficar()

Utilizamos la sintaxis:

[nombre del objeto].[nombre del método]

Es decir antecedemos al nombre del método el nombre del objeto y el operador punto

Ahora bien que pasa si queremos llamar dentro de la clase a otro método que pertenece a la misma clase, la sintaxis es la siguiente:

self.[nombre del método]

Es importante tener en cuenta que esto solo se puede hacer cuando estamos dentro de la misma clase.

Confeccionaremos un problema que haga llamadas entre métodos de la misma clase.

Problema:Confeccionar una clase Tabla que permita indicarle en el constructor la cantidad de filas y columnas. Definir otra responsabilidad que podamos cargar un dato en una determinada fila y columna. Finalmente debe mostrar los datos en una tabla HTML.

class Tabla: mat=[] cantfilas=0 cantcolumnas=0

def __init__(self,fi,co): self.cantfilas=fi self.cantcolumnas=co for f in range(0,fi): self.mat.append([]) for c in range(0,co): self.mat[f].append('')

def cargar(self,fi,col,valor): self.mat[fi][col]=valor

def iniciotabla(self): print '<table border="1">' def iniciofila(self): print '<tr>'

def mostrar(self,fi,co): print '<td>' print self.mat[fi][co] print '</td>'

def finfila(self): print '</tr>'

def fintabla(self): print '</table>'

def graficar(self): self.iniciotabla()

Page 55: Manual Phyton

for f in range(0,self.cantfilas): self.iniciofila() for c in range(0,self.cantcolumnas): self.mostrar(f,c) self.finfila() self.fintabla() tabla1=Tabla(3,4)tabla1.cargar(0,0,1)tabla1.cargar(0,1,2)tabla1.cargar(0,2,3)tabla1.cargar(0,3,4)tabla1.cargar(1,0,5)tabla1.cargar(1,1,6)tabla1.cargar(1,2,7)tabla1.cargar(1,3,8)tabla1.cargar(2,0,9)tabla1.cargar(2,1,10)tabla1.cargar(2,2,11)tabla1.cargar(2,3,12)tabla1.graficar()

Vamos por parte, primero veamos los tres atributos definidos,el primero se trata de una lista donde almacenaremos todos los valores que contendrá la tabla HTML y otros dos atributos que indican la dimensión de la tabla HTML (cantidad de filas y columnas):

mat=[] cantfilas=0 cantcolumnas=0

El constructor recibe como parámetros la cantidad de filas y columnas que tendrá la tabla, además creamos la lista con tantas filas como indica el parámetro fi e insertamos una lista en cada componente (es decir que cada componente de la lista es una lista que representa los elementos de la fila respectiva) Dentro de un for interno agregamos string vacíos a cada elemento de la lista interna:

self.cantfilas=fi self.cantcolumnas=co for f in range(0,fi): self.mat.append([]) for c in range(0,co): self.mat[f].append('')

Otro método de vital importancia es el de cargar datos. Llegan como parámetro la fila, columna y dato a almacenar:

def cargar(self,fi,col,valor): self.mat[fi][col]=valor

Otro método muy importante es el graficar:

def graficar(self): self.iniciotabla() for f in range(0,self.cantfilas): self.iniciofila() for c in range(0,self.cantcolumnas): self.mostrar(f,c) self.finfila() self.fintabla()

Page 56: Manual Phyton

El método graficar debe hacer las salidas de datos dentro de una tabla HTML. Para simplificar el algoritmo definimos otros cinco métodos que tienen por objetivo hacer la generación del código HTML propiamente dicho. Así tenemos el método iniciotabla que hace la salida de la marca table e inicialización del atributo border:

def iniciotabla(self): print '<table border="1">'

De forma similar los otros métodos son:

def iniciofila(self): print '<tr>'

def mostrar(self,fi,co): print '<td>' print self.mat[fi][co] print '</td>'

def finfila(self): print '</tr>'

def fintabla(self): print '</table>'

Si bien podíamos hacer todo esto en el método graficar y no hacer estos cinco métodos, la simplicidad del código aumenta a medida que subdividimos los algoritmos. Esto es de fundamental importancia con algoritmos más complejos./p>

Lo que nos importa ahora ver es como llamamos a métodos que pertenecen a la misma clase:

def graficar(self): self.iniciotabla() for f in range(0,self.cantfilas): self.iniciofila() for c in range(0,self.cantcolumnas): self.mostrar(f,c) self.finfila() self.fintabla()

Es decir le antecedemos la palabra self al nombre del método a llamar. De forma similar a como accedemos a los atributos de la clase.

Por último debemos definir un objeto de la clase Tabla y llamar a los métodos respectivos:

tabla1=Tabla(3,4)tabla1.cargar(0,0,1)tabla1.cargar(0,1,2)tabla1.cargar(0,2,3)tabla1.cargar(0,3,4)tabla1.cargar(1,0,5)tabla1.cargar(1,1,6)tabla1.cargar(1,2,7)tabla1.cargar(1,3,8)tabla1.cargar(2,0,9)tabla1.cargar(2,1,10)tabla1.cargar(2,2,11)tabla1.cargar(2,3,12)tabla1.graficar()

Es importante notar que donde definimos un objeto de la clase Tabla no llamamos a los métodos iniciotabla(), iniciofila(), etc.

Page 57: Manual Phyton

Problema resuelto

Confeccionar una clase Tabla que permita indicarle en el constructor la cantidad de filas y columnas. Definir otra responsabilidad que podamos cargar un dato en una determinada fila y columna. Finalmente debe mostrar los datos en una tabla HTML.

class Tabla: mat=[] cantfilas=0 cantcolumnas=0

def __init__(self,fi,co): self.cantfilas=fi self.cantcolumnas=co for f in range(0,fi): self.mat.append([]) for c in range(0,co): self.mat[f].append('')

def cargar(self,fi,col,valor): self.mat[fi][col]=valor

def iniciotabla(self): print '<table border="1">' def iniciofila(self): print '<tr>'

def mostrar(self,fi,co): print '<td>' print self.mat[fi][co] print '</td>'

def finfila(self): print '</tr>'

def fintabla(self): print '</table>'

def graficar(self): self.iniciotabla() for f in range(0,self.cantfilas): self.iniciofila() for c in range(0,self.cantcolumnas): self.mostrar(f,c) self.finfila() self.fintabla()

Page 58: Manual Phyton

tabla1=Tabla(3,4)tabla1.cargar(0,0,1)tabla1.cargar(0,1,2)tabla1.cargar(0,2,3)tabla1.cargar(0,3,4)tabla1.cargar(1,0,5)tabla1.cargar(1,1,6)tabla1.cargar(1,2,7)tabla1.cargar(1,3,8)tabla1.cargar(2,0,9)tabla1.cargar(2,1,10)tabla1.cargar(2,2,11)tabla1.cargar(2,3,12)tabla1.graficar()

Resultado:

Problema Propuesto

Confeccionar una clase Tabla que permita indicarle en el constructor la cantidad de filas y columnas. Definir otra responsabilidad que podamos cargar un dato en una determinada fila y columna además de definir su color de fuente. Finalmente debe mostrar los datos en una tabla HTML.

Ver soluciónclass Tabla: mat=[] color=[] cantfilas=0 cantcolumnas=0

def __init__(self,fi,co): self.cantfilas=fi self.cantcolumnas=co for f in range(0,fi): self.mat.append([]) self.color.append([]) for c in range(0,co): self.mat[f].append('') self.color[f].append('')

def cargar(self,fi,col,valor,colorletra): self.mat[fi][col]=valor self.color[fi][col]=colorletra

def iniciotabla(self): print '<table border="1">'

Page 59: Manual Phyton

def iniciofila(self): print '<tr>'

def mostrar(self,fi,co): print '<td style="color:'+self.color[fi][co]+'">' print self.mat[fi][co] print '</td>'

def finfila(self): print '</tr>'

def fintabla(self): print '</table>'

def graficar(self): self.iniciotabla() for f in range(0,self.cantfilas): self.iniciofila() for c in range(0,self.cantcolumnas): self.mostrar(f,c) self.finfila() self.fintabla() tabla1=Tabla(3,4)tabla1.cargar(0,0,1,'#ff0000')tabla1.cargar(0,1,2,'#ff0000')tabla1.cargar(0,2,3,'#ff0000')tabla1.cargar(0,3,4,'#ff0000')tabla1.cargar(1,0,5,'#00ff00')tabla1.cargar(1,1,6,'#00ff00')tabla1.cargar(1,2,7,'#00ff00')tabla1.cargar(1,3,8,'#00ff00')tabla1.cargar(2,0,9,'#0000ff')tabla1.cargar(2,1,10,'#0000ff')tabla1.cargar(2,2,11,'#0000ff')tabla1.cargar(2,3,12,'#0000ff')tabla1.graficar()

Herencia

Otra característica que tiene que tener un lenguaje para considerarse orientado a objetos es la HERENCIA.

La herencia significa que se pueden crear nuevas clases partiendo de clases existentes, que tendrá todas los atributos y los métodos de su 'superclase' o 'clase padre' y además se le podrán añadir otros atributos y métodos propios.

En Python, a diferencia de otros lenguajes orientados a objetos (Java, C#), una clase puede derivar de varias clases, es decir, Python permite la herencia múltiple.

Superclase o clase padre

Clase de la que desciende o deriva una clase. Las clases hijas (descendientes) heredan (incorporan) automáticamente los atributos y métodos de la la clase padre.

Subclase

Clase desciendiente de otra. Hereda automáticamente los atributos y métodos de su superclase. Es una especialización de otra clase. Admiten la definición de nuevos atributos y métodos para aumentar la especialización de la clase.

Page 60: Manual Phyton

Veamos algunos ejemplos teóricos de herencia:

1) Imaginemos la clase Vehículo. Qué clases podrían derivar de ella?

Vehiculo

Colectivo Moto Auto FordK Renault 9

Siempre hacia abajo en la jerarquía hay una especialización (las subclases añaden nuevos atributos y métodos)

2) Imaginemos la clase Software. Qué clases podrían derivar de ella?

Software

DeAplicacion DeBase

ProcesadorTexto PlanillaDeCalculo SistemaOperativo

Word WordPerfect Excel Lotus123 Linux Windows

Si vemos que dos clase responden a la pregunta ClaseA "..es un.." ClaseB es posible que haya una relación de herencia.Por ejemplo:Auto "es un" VehiculoCirculo "es una" FiguraMouse "es un" DispositivoEntradaSuma "es una" Operacion

Ahora plantearemos el primer problema utilizando herencia en Python. Supongamos que necesitamos implementar dos clases que llamaremos Suma y Resta. Cada clase tiene como atributo valor1, valor2 y resultado. Los métodos a definir son cargar1 (que inicializa el atributo valor1), carga2 (que inicializa el atributo valor2), operar (que en el caso de la clase "Suma" suma los dos atributos y en el caso de la clase "Resta" hace la diferencia entre valor1 y valor2, y otro método mostrarresultado.Si analizamos ambas clases encontramos que muchos atributos y métodos son idénticos. En estos casos es bueno definir una clase padre que agrupe dichos atributos y responsabilidades comunes.

La relación de herencia que podemos disponer para este problema es:

Operacion

Suma Resta

Solamente el método operar es distinto para las clases Suma y Resta (esto hace que no lo podamos disponer en la clase Operacion), luego los métodos cargar1, cargar2 y mostrarresultado son idénticos a las dos clases, esto hace que podamos disponerlos en la clase Operacion. Lo mismo los atributos valor1, valor2 y resultado se definirán en la clase padre Operacion.

En Pyton la codificación de estas tres clases es la siguiente:

class Operacion: def cargar1(self,v1): self.valor1=v1 def cargar2(self,v2): self.valor2=v2 def imprimir(self): print self.resultado

Page 61: Manual Phyton

print '<br>'

class Suma(Operacion): def operar(self): self.resultado=self.valor1+self.valor2

class Resta(Operacion): def operar(self): self.resultado=self.valor1-self.valor2

s=Suma()s.cargar1(10)s.cargar2(20)s.operar()print 'La suma es:'s.imprimir()r=Resta()r.cargar1(10)r.cargar2(2)r.operar()print 'La resta es:'r.imprimir()

Veamos como es la sintaxis para indicar que una clase hereda de otra:

class Suma(Operacion):

Indicamos entre paréntesis el nombre de la clase padre (con esto estamos indicando que todos los métodos y atributos de la clase Operación son también métodos de la clase Suma.

Luego la característica que añade la clase Suma es el siguiente método:

def operar(self): self.resultado=self.valor1+self.valor2

El método operar puede acceder a los atributos heredados.

Ahora podemos decir que la clase Suma tiene cuatro métodos (tres heredados y uno propio) y 3 atributos

Si creamos un objeto de la clase Suma tenemos:

s=Suma()s.cargar1(10)s.cargar2(20)s.operar()print 'La suma es:'s.imprimir()

Podemos llamar tanto al método propio de la clase Suma "operar()" como a los métodos heredados. Quien utilice la clase Suma solo debe conocer que métodos tiene (independientemente que pertenezcan a la clase Suma o a una clase superior)

La lógica es similar para declarar la clase Resta:

class Resta(Operacion): def operar(self): self.resultado=self.valor1-self.valor2

y la definición de un objeto de dicha clase:

Page 62: Manual Phyton

r=Resta()r.cargar1(10)r.cargar2(2)r.operar()print 'La resta es:'r.imprimir()

La clase Operación agrupa en este caso un conjunto de atributos y métodos comunes a un conjunto de subclases (Suma, Resta). No tiene sentido definir objetos de la clase Operacion.

El planteo de jerarquías de clases es una tarea compleja que requiere un perfecto entendimiento de todas las clases que intervienen en un problema, cuales son sus atributos y responsabilidades.

Problema resuelto

Declarar una clase Operacion que defina los metodos para cargar dos valores y muestre el resultado. Luego heredar de esta clase para definir los conceptos de suma y resta.

class Operacion: def cargar1(self,v1): self.valor1=v1 def cargar2(self,v2): self.valor2=v2 def imprimir(self): print self.resultado print '<br>'

class Suma(Operacion): def operar(self): self.resultado=self.valor1+self.valor2

class Resta(Operacion): def operar(self): self.resultado=self.valor1-self.valor2

s=Suma()s.cargar1(10)s.cargar2(20)s.operar()print 'La suma es:'s.imprimir()r=Resta()r.cargar1(10)r.cargar2(2)r.operar()print 'La resta es:'r.imprimir()

Page 63: Manual Phyton

Resultado:La suma es: 30 La resta es: 8

Método especial __str__

Podemos hacer que se ejecute un método definido por nosotros cuando pasamos un objeto a la función print o cuando llamamos a la función str.

Que sucede cuando llamamos a la función print y le pasamos como parámetro un objeto?

class Persona: def __init__(self,nom,ape): self.nombre=nom self.apellido=ape per=Persona('Jose','Rodriguez')print per

Nos muestra algo parecido a esto:

<__main__.Persona instance at 0xf9e0a60ec5872050>

Python nos permite redefinir el método que se debe ejecutar. Esto se hace definiendo en la clase el método especial __str__

En el ejemplo anterior si queremos que se muestre el nombre y apellido separados por coma cuando llamemos a la función print el código que debemos implementar es el siguiente:

class Persona: def __init__(self,nom,ape): self.nombre=nom self.apellido=ape def __str__(self): cadena=self.nombre+','+self.apellido return cadena

per=Persona('Jose','Rodriguez')print per

Como vemos debemos implementar el método __str__ y retornar un string, este luego será el que imprime la función print:

def __str__(self): cadena=self.nombre+','+self.apellido return cadena

Esta característica definida en Python nos permite crear programas muy legibles y flexibles.

El método __str__ también se ejecuta si llamamos a la función str y pasamos como parámetro un objeto que tiene definido dicho método:

class Persona: def __init__(self,nom,ape): self.nombre=nom self.apellido=ape

Page 64: Manual Phyton

def __str__(self): cadena=self.nombre+','+self.apellido return cadena

per1=Persona('Jose','Rodriguez')per2=Persona('Ana','Martinez')print str(per1)+'-'+str(per2) # Jose,Rodriguez-Ana,Martinez

Problema resuelto

Crear una clase URL que permita inicializar la dirección que apunta y el texto que debe mostrar. Definir el método __str__ que genere un string con el elemento HTML de hipervínculo.

class URL: def __init__(self,dir,men): self.direccion=dir self.mensaje=men def __str__(self): cadena='<a href="%s">%s</a>' % (self.direccion,self.mensaje) return cadena

url1=URL('http://www.google.com.ar','Google')url2=URL('http://www.yahoo.com.ar','Yahoo')url3=URL('http://www.live.com','Live')print url1print url2print url3

Resultado:Google Yahoo Live

Redefinición de los operadores matemáticos con objetos

Python nos permite redefinir los operadores matemáticos cuando planteamos una clase.

Los métodos especiales que debemos implementar son los siguientes:

Para el operador +:

__add__(self,objeto2)

Para el operador -:

__sub__(self,objeto2)

Para el operador *:

__mul__(self,objeto2)

Para el operador /:

__div__(self,objeto2)

Page 65: Manual Phyton

Veamos con un ejemplo la sintaxis para redefinir el operador +. Crearemos una clase Cliente de un banco y redefiniremos el operador + para que nos retorne la suma de los depósitos de los dos clientes que estamos sumando.

class Cliente: def __init__(self,nom,mon): self.nombre=nom self.monto=mon def __add__(self,objeto2): s=self.monto+objeto2.monto return s

cli1=Cliente('Ana',1200)cli2=Cliente('Luis',1500)print 'El total depositado es 'print cli1+cli2

Es muy importante tener en cuenta que debemos redefinir un operador matemático siempre y cuando haga nuestro programa más legible.

Debemos redefinir los operadores +,-,*,/ etc. solo para las clases que con solo leer su nombre el programador intuya que operación implementaría dicho operador.

Problema resuelto

Crear una clase Cliente de un banco y redefinir el operador + para que nos retorne la suma de los depósitos de los dos clientes que estamos sumando.

class Cliente: def __init__(self,nom,mon): self.nombre=nom self.monto=mon def __add__(self,objeto2): s=self.monto+objeto2.monto return s

cli1=Cliente('Ana',1200)cli2=Cliente('Luis',1500)print 'El total depositado es 'print cli1+cli2

Resultado:El total depositado es 2700

Redefinición de los operadores relacionales con objetos

Python también nos permite redefinir los operadores relacionales cuando planteamos una clase.

Los métodos especiales que podemos implementar son los siguientes:

Para el operador ==:

__eq__(self,objeto2)

Page 66: Manual Phyton

Para el operador !=:

__ne__(self,objeto2)

Para el operador >:

__gt__(self,objeto2)

Para el operador >=:

__ge__(self,objeto2)

Para el operador <:

__lt__(self,objeto2)

Para el operador <=:

__le__(self,objeto2)

Es importante recordar que una redefinición de un operador tiene sentido si ayuda y hace más claro nuestro algoritmo.

Veamos con un ejemplo la sintaxis para redefinir todos estos operadores relacionales. Crearemos una clase Persona que tiene como atributo el nombre y la edad. El operador == retornará verdadero si las dos personas tienen la misma edad, el operador > retornará True si la edad del objeto de la izquierda tiene una edad mayor a la edad del objeto de la derecha del operador >, y así sucesivamente

class Persona: def __init__(self,nom,ed): self.nombre=nom self.edad=ed def __eq__(self,objeto2): if self.edad==objeto2.edad: return True else: return False def __ne__(self,objeto2): if self.edad!=objeto2.edad: return True else: return False def __gt__(self,objeto2): if self.edad>objeto2.edad: return True else: return False def __ge__(self,objeto2): if self.edad>=objeto2.edad: return True else: return False def __lt__(self,objeto2): if self.edad<objeto2.edad: return True else: return False def __le__(self,objeto2): if self.edad<=objeto2.edad: return True else: return False

Page 67: Manual Phyton

per1=Persona('juan',22)per2=Persona('ana',22)if per1==per2: print 'Las dos personas tienen la misma edad.'else: print 'No tienen la misma edad.'

Como pedemos observar planteamos un método por cada operdor relacional:

def __eq__(self,objeto2): if self.edad==objeto2.edad: return True else: return False

El método recibe como referencia (self) la dirección del objeto ubicado a la izquierda del operador relacionar y como parámetro (objeto2) la referencia del objeto ubicado a la derecha del operador. Solo nos queda analizar el atributo edad de cada objeto y retornar True si los dos almacenan el mismo valor, en caso contrario retornar False.

Problema resuelto

Crear una clase Persona que tenga como atributo el nombre y la edad. El operador == retornará verdadero si las dos personas tienen la misma edad, el operador > retornará True si la edad del objeto de la izquierda tiene una edad mayor a la edad del objeto de la derecha del operador >, y así sucesivamente

class Persona: def __init__(self,nom,ed): self.nombre=nom self.edad=ed def __eq__(self,objeto2): if self.edad==objeto2.edad: return True else: return False def __ne__(self,objeto2): if self.edad!=objeto2.edad: return True else: return False def __gt__(self,objeto2): if self.edad>objeto2.edad: return True else: return False def __ge__(self,objeto2): if self.edad>=objeto2.edad: return True else: return False def __lt__(self,objeto2):

Page 68: Manual Phyton

if self.edad<objeto2.edad: return True else: return False def __le__(self,objeto2): if self.edad<=objeto2.edad: return True else: return False

per1=Persona('juan',22)per2=Persona('ana',22)if per1==per2: print 'Las dos personas tienen la misma edad.'else: print 'No tienen la misma edad.'

Resultado:Las dos personas tienen la misma edad.

Problema Propuesto

Plantear una clase Rectangulo. Definir dos atributos (ladomenor y ladomayor). Redefinir el operador == de tal forma que tengan en cuenta la superficie del rectángulo.

Ver solución

class Rectangulo: def __init__(self,lmen,lmay): self.lmenor=lmen self.lmayor=lmay def retornarsuperficie(self): return self.lmenor*self.lmayor def __eq__(self,objeto2): if self.retornarsuperficie()==objeto2.retornarsuperficie(): return True else: return False

rectangulo1=Rectangulo(10,10)rectangulo2=Rectangulo(5,20)if rectangulo1==rectangulo2: print 'Los rectangulos tienen la misma superficie'else: print 'Los rectangulos no tienen la misma superficie'

Las cadenas tratadas como objetos

Ahora que hemos introducido los conceptos básicos de objetos veamos más profundo el concepto de cadenas (string) en Python.

Page 69: Manual Phyton

En Python todo es un objetos, por lo que cuando definimos una cadena estamos definiendo un objeto.

Como hemos visto toda clase tiene una serie de métodos, veremos los métodos principales que tiene la clase que en Python administra una cadena.

Los métodos:

capitalize()Retorna otra cadena con el primer caracter en mayúsculas.

cadena='ana' print cadena.capitalize() #Ana print cadena #ana

Es importante notar que no se modifica el contenido de la variable 'cadena'. El método capitalize() retorna otra cadena con el primero en mayúsculas.

upper()Retorna otra cadena con todos los caracteres convertidos a mayúscula.

cadena1='ana' cadena2=cadena1.upper() print cadena2 #ANA

lower()Retorna otra cadena con todos los caracteres convertidos a minúsculas.

cadena1='Ana' cadena2=cadena1.lower() print cadena2 #ana

isupper()Retorna True si todos los caracteres de la cadena están en mayúsculas.

cadena='ANA' if cadena.isupper(): print 'La cadena '+cadena+' esta toda en mayusculas'

islower()Retorna True si todos los caracteres de la cadena están en minúsculas.

cadena1='ana' if cadena.islower(): print 'La cadena '+cadena+' esta toda en minusculas'

isdigit()Retorna verdadero si todos los caracteres de la cadena son dígitos.

cadena='120' if cadena.isdigit(): print 'Todos los caracteres de la cadena son numeros'

Si al menos uno de los caracteres es distinto a un dígito retorna False. Inclusive si tiene el caracter punto.

isalpha()Retorna True si todos los caracteres son alfabéticos.

cadena='Hola Mundo' if cadena.isalpha(): print 'Todos los caracteres de la cadena son del alfabeticos' else: print 'No todos los caracteres de la cadena son del alfabeticos'

En el ejemplo superior ejecuta el bloque del else ya que la cadena contiene un caracter de espacio.

isspace()Retorna verdadero si todos los caracteres de la cadena son espacios en blanco

cadena=' ' if cadena.isspace(): print 'Todos los caracteres de la cadena son espacios en blanco'

Page 70: Manual Phyton

isalnum()Retorna True si todos los caracteres de la cadena son números o caracteres alfabéticos.

cadena='cordoba2008' if cadena.isalnum(): print 'Todos los caracteres son numeros o alfabeticos'

find('cadena',[inicio],[fin])Retorna la posición donde se encuentra el valor del primer parámetro en el string. Si no se encuentra retorna -1. Podemos indicar como segundo y tercer parámetro a partir de que posición y hasta que posición de la cadena hacer la búsqueda.

cadena='esto es una prueba y es solo eso' pos=cadena.find('es') print pos #0

Retorna 0 ya que los dos primeros caracteres son la cadena 'es', es decir retorna la primera aparición del string.

cadena='esto es una prueba y es solo eso'pos=cadena.find('es',5)print pos #5

En este otro ejemplo comenzamos la búsqueda a partir de la posición 5. Si no indicamos el tercer parámetro la búsqueda la hace hasta el final de la cadena

rfind('cadena',[inicio],[fin])Igual al método find con la diferencia que la búsqueda comienza desde el final.

cadena='esto es una prueba y es solo eso' pos=cadena.rfind('es') print pos #29

count('cadena',[inicio],[fin])Retorna la cantidad de veces que la cadena se repite en el string.

cadena='esto es una prueba y es solo eso' cant=cadena.count('es') print cant #4

replace('cadena1','cadena2',[maximo])Retorna un string remplazando todas las ocurrencias de cadena1 por cadena2. Podemos eventuamente indicar la cantidad máxima de remplazos.

cadena1='esto es una prueba y es solo eso' cadena2=cadena1.replace('es','ES') print cadena2 #ESto ES una prueba y ES solo ESo

split('caracter separador',[maximo])El método split retorna una lista dividiendo el string por el caracter indicado en el primer parámetro. Podemos pasar un segundo parámetro indicando la cantidad de trozos a general, el último elemento de la lista almacena el resto del string.

cadena='esto es una prueba y es solo eso' lista=cadena.split(' ') print lista #['esto', 'es', 'una', 'prueba', 'y', 'es', 'solo',

'eso'] print len(lista) #8 lista=cadena.split(' ',2) print lista #['esto', 'es', 'una prueba y es solo eso'] print len(lista) #3

rsplit('caracter separador',[maximo])Semejante a split pero procesando desde el final del string. En caso de indicar maximo el primer elemento de la lista almacena el trozo restante.

cadena='esto es una prueba y es solo eso' lista=cadena.rsplit(' ') print lista #['esto', 'es', 'una', 'prueba', 'y', 'es', 'solo',

'eso'] print len(lista) #8 lista=cadena.rsplit(' ',2) print lista #['esto es una prueba y es', 'solo', 'eso']

Page 71: Manual Phyton

print len(lista) #3

splitlines()Retorna una lista dividiendo el string con los retornos de carro contenidos en el mismo.

mensaje="""Primer linea Segunda linea Tercer linea Cuarta linea""" lista=mensaje.splitlines() print lista #['Primer linea', ' Segunda linea', ' Tercer linea', ' Cuarta linea']

swapcase()Retorna un string transformando los caracteres minúsculas a mayúsculas y los mayúsculas a minúsculas.

cadena1='Sistema de Facturacion' cadena2=cadena1.swapcase() print cadena2 #sISTEMA DE fACTURACION

rjust(ancho,caracter de relleno)Retorna un string justificado a derecha y rellenando el lado izquierdo con caracteres según el segundo parámetro. La nueva cadena toma un largo indicado según el valor del primer parámetro.

cadena='200' cadena2=cadena.rjust(5,'$') print cadena2 #$$200

ljust(ancho,caracter de relleno)Similar a rjust con la salvedad que se justifica a derecha el string.

cadena='200' cadena2=cadena.ljust(5,'$') print cadena2 #200$$

center(ancho,caracter de relleno)El string original se centra.

cadena='200' cadena2=cadena.center(5,'$') print cadena2 #$200$

Problema resuelto

Confeccionar una función que reciba una lista de valores y los muestre en columna y justificados a derecha.

def mostrar(lista): print '<pre>' for v in lista: print v.rjust(10,' ') print '<br>' print '<pre>'

l=['234','12','345534','234','1','45']mostrar(l)

Resultado: 234

12

345534

Page 72: Manual Phyton

234

1

45

Problema Propuesto

Confeccionar una función que reciba una oración y retorne la palabra mayor alfabéticamente

Ver solucióndef mayoralfa(cadena): lista=cadena.split(' ') mayor=lista[0] for pa in lista: if pa>mayor: mayor=pa return mayor

oracion='esto es una prueba y es'print mayoralfa(oracion)

Las listas tratadas como objetos

Ahora veremos más profundamente el concepto de listas en Python y los métodos que provee su clase.

Los métodos:

append(elemento)El método append añade un elemento al final de la lista.

lista=['juan','ana','luis'] lista.append('carlos') print lista #['juan', 'ana', 'luis', 'carlos']

extend(elementos)El método extend procesa la secuencia de elementos del parámetro y los añade uno a uno a la lista. La diferencia con el método append es que append siempre añade un único elemento a la lista y extend añade tantos elementos como tenga la secuencia.

lista=['juan','ana','luis'] lista.extend(['uno','dos']) print lista #['juan', 'ana', 'luis', 'uno', 'dos']

Ahora la lista tiene 5 elementos, es decir se añadieron 2 nuevas componentes a la lista.En cambio si utilizamos append el resultado es:

lista=['juan','ana','luis']lista.append(['uno','dos'])print lista #['juan', 'ana', 'luis', ['uno', 'dos']] Ahora la lista tiene cuatro elementos y el último elemento es una lista también.

insert(posición,elemento)El método insert añade un elemento en la posición que le indicamos en el primer parámetro.

Page 73: Manual Phyton

lista=['juan','ana','luis'] lista.insert(0,'carlos') print lista #['carlos', 'juan', 'ana', 'luis']

En este ejemplo insertamos la cadena 'carlos' al principio de la lista, ya que pasamos la posición 0, no se borra el elemento que se encuentra en la posición 0 sino se desplaza a la segunda posición.Si indicamos una posición que no existe porque supera a la posición del último elemento se inserta al final de la lista.

pop([posicion]El método pop si lo llamamos sin parámetro nos retorna y borra la información del último nodo de la lista. Si en cambio pasamos un entero este indica la posición del cual se debe extraer.

lista=['juan','ana','luis','marcos'] elemento=lista.pop() print elemento #marcos print lista #['juan', 'ana', 'luis'] print lista.pop(1) #ana print lista #['juan', 'luis']

remove(elemento)Borra el primer nodo que coincide con la información que le pasamos como parámetro.

lista=['juan','ana','luis','marcos','ana'] lista.remove('ana') print lista #['juan', 'luis', 'marcos', 'ana']

count(elemento)Retorna la cantidad de veces que se repite la información que le pasamos como parámetro.

lista=['juan','ana','luis','marcos','ana'] print lista.count('ana') #2

index(elemento,[inicio],[fin])Retorna la primera posición donde se encuentra el primer parámetro en la lista. Podemos eventualmente indicarle a partir de que posición empezar a buscar y en que posición terminar la búsqueda.Si no lo encuentra en la lista genera un error: ValueError: list.index(x): x not in list

lista=['juan','ana','luis','marcos','ana'] print lista.index('ana') #1

sort()Ordena la lista de menor a mayor.

lista=['juan','ana','luis','marcos','ana'] lista.sort() print lista #['ana', 'ana', 'juan', 'luis', 'marcos']

reverse()Invierte el orden de los elementos de la lista.

lista=['juan','ana','luis','marcos','ana'] lista.reverse() print lista #['ana', 'marcos', 'luis', 'ana', 'juan']

Si necesitamos borrar un nodo de la lista debemos utilizar el comando del que provee Python:

lista=['juan','ana','luis','marcos']del lista[2]print lista #['juan', 'ana', 'marcos']

Podemos utilizar el concepto de porciones para borrar un conjunto de elementos de la lista:

Si queremos borrar los elementos de la posición 2 hasta la 3: lista=['juan','ana','carlos','maria','pedro']del lista[2:4]print lista # ['juan', 'ana', 'pedro']

Si queremos borrar desde la 2 hasta el final: lista=['juan','ana','carlos','maria','pedro']del lista[2:]print lista # ['juan', 'ana']

Page 74: Manual Phyton

Si queremos borrar todos desde el principio hasta la posición 3 sin incluirla: lista=['juan','ana','carlos','maria','pedro']del lista[:3]print lista # ['maria', 'pedro']

Si queremos ir borrando de a uno de por medio: lista=['juan','ana','carlos','maria','pedro']del lista[::2]print lista # ['ana', 'maria']

Si necesitamos modificar el contenido de un nodo de la lista debemos utilizar el operador de asignación:

lista=['juan','ana','luis','marcos']lista[2]='xxxxx'print lista #['juan', 'ana', 'xxxxx', 'marcos']

Problema resuelto

Crear una lista con 30 valores aleatorios comprendidos entre 1 y 300.Efectuar las siguientes operaciones (Luego de cada operación mostrar el estado de la lista):- Borrar el primer y último elemento de la lista.- Insertar un elemento al final con la suma de todos los elementos actuales.- Insertar un elemento entre el primero y el segundo elemento de la lista con el valor 125.

import random

lista=[]for x in range(1,50): valor=random.randint(1,300) lista.append(valor)print listaprint '<br>'del lista[0]del lista[-1]print listaprint '<br>'suma=0for x in range(1,len(lista)): suma=suma+lista[x]lista.append(suma)print listaprint '<br>'lista.insert(1,125)print lista

RESULTADO:

[289, 288, 168, 110, 297, 288, 80, 256, 88, 165, 44, 266, 211, 40, 185, 124, 47, 213, 221, 39, 211, 209, 205, 232, 125, 285, 116, 195, 295, 106, 171, 101, 66, 74, 24, 240, 80, 10, 40, 218, 38, 193, 221, 45, 12, 143, 176, 64, 24] [288, 168, 110, 297, 288, 80, 256, 88, 165, 44, 266, 211, 40, 185, 124, 47, 213, 221, 39, 211, 209, 205, 232, 125, 285, 116, 195, 295, 106, 171, 101, 66, 74, 24, 240, 80, 10, 40, 218, 38, 193, 221, 45, 12, 143, 176, 64] [288, 168, 110, 297, 288, 80, 256, 88, 165, 44, 266, 211, 40, 185, 124, 47, 213, 221, 39, 211, 209, 205, 232,

Page 75: Manual Phyton

125, 285, 116, 195, 295, 106, 171, 101, 66, 74, 24, 240, 80, 10, 40, 218, 38, 193, 221, 45, 12, 143, 176, 64, 6737] [288, 125, 168, 110, 297, 288, 80, 256, 88, 165, 44, 266, 211, 40, 185, 124, 47, 213, 221, 39, 211, 209, 205, 232, 125, 285, 116, 195, 295, 106, 171, 101, 66, 74, 24, 240, 80, 10, 40, 218, 38, 193, 221, 45, 12, 143, 176, 64, 6737]

Problema Propuesto

Crear una lista con 10 valores aleatorios comprendidos entre 1 y 5.- Insertar un nodo al final de la lista con el mayor elemento de la lista.- Insertar un nodo al principio de la lista con la suma de los primeros 5 nodos.- Imprimir la cantidad de veces que se repite la información del segundo nodo en la lista.

Ver solución

import random

lista=[]for x in range(1,10): valor=random.randint(1,5) lista.append(valor)print listaprint '<br>'mayor=lista[0]for valor in lista: if valor>mayor: mayor=valorlista.insert(0,mayor)print listaprint '<br>'print lista.count(lista[1])

Los diccionarios tratados como objetos

Habíamos visto la estructura de datos tipo diccionario que utiliza una clave para acceder a un valor. El subíndice puede ser un entero, un string etc. Un diccionario vincula una clave y un valor.

Los diccionarios en Python también son objetos y como tales tienen una serie de métodos que nos permiten administrarlos:

keys()Retorna una lista con todas las claves del diccionario.

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'} lista=diccionario.keys() print lista # ['house', 'window', 'bed', 'red']

values()Retorna una lista con todos los valores almacenados en el diccionario.

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'} lista=diccionario.values() print lista # ['casa', 'ventana', 'cama', 'rojo']

items()Retorna una lista que contiene en cada nodo una tupla con la clave y valor del diccionario.

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'} lista=diccionario.items() print lista # [('house', 'casa'), ('window', 'ventana'), ('bed', 'cama'),

('red', 'rojo')]

Page 76: Manual Phyton

pop(clave,[valor])Extrae el valor de la clave que pasamos como parámetro y borra el elemento del diccionario. Genera un error si no se encuentra dicha clave, salvo que se inicialice un segundo parámetro que será el dato que retornará.

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'} valor=diccionario.pop('window') print valor # ventana print diccionario #{'house': 'casa', 'bed': 'cama', 'red': 'rojo'}

Si no encuentra la clave en el diccionario y hemos indicado un segundo parámetro al método pop será dicho valor el que retorne:

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'}valor=diccionario.pop('love','clave no encontrada')print valor # clave no encontrada

has_key(clave)Retorna True si la clave se encuentra en el diccionario, False en caso contrario.

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'} if diccionario.has_key('love'): print 'Si tiene la clave buscada' else: print 'No existe la clave buscada'

clear()Elimina todos los elementos del diccionario.

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'} diccionario.clear() print diccionario # {}

copy()Se genera una copia idéntica del diccionario actual en otra parte de memoria.

diccionario1={'house':'casa','red':'rojo','bed':'cama','window':'ventana'} diccionario2=diccionario1.copy() print diccionario2 #{'house': 'casa', 'window': 'ventana', 'red': 'rojo', 'bed':

'cama'} diccionario1['house']='xxxxx' print diccionario2 #{'house': 'casa', 'window': 'ventana', 'red': 'rojo', 'bed':

'cama'}

Es importante hacer notar que no es lo mismo:

diccionario2=diccionario1

Con la asignación anterior no se esta creando un segundo diccionario sinó se tiene dos variables que referencian al mismo objeto.

popitem()Retorna un elemento del diccionario y lo elimina. Como no hay un sentido de orden en el diccionario se extrae uno al azar.

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'} elemento=diccionario.popitem() print elemento print diccionario

Para saber cual se extrajo se debe ejecutar el algoritmo.

update(diccionario2)Modifica el diccionario actual agregando los elementos del diccionario2, si una clave está repetida se modifica su valor.

diccionario1={'uno':'1','dos':'2','tres':'3333'} diccionario2={'tres':'3','cuatro':'4','cinco':'5'}

Page 77: Manual Phyton

diccionario1.update(diccionario2) print diccionario1 #{'cuatro': '4', 'cinco': '5', 'dos': '2', 'tres': '3', 'uno':

'1'}

Además seguimos contando con el comando del para borrar elementos del diccionario:

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'}del diccionario['house']print diccionario #{'window': 'ventana', 'bed': 'cama', 'red': 'rojo'}

El cambio o agregado de un valor al diccionario se hace mediante la asignación:

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'}diccionario['red']='colorado'diccionario['blue']='azul'print diccionario # {'house': 'casa', 'window': 'ventana', 'bed': 'cama', 'red': 'colorado','blue': 'azul'}

La cantidad de elementos mediante la función len:

diccionario={'house':'casa','red':'rojo','bed':'cama','window':'ventana'}print len(diccionario) # 4

Problema resuelto

Definir un diccionario para almacenar el nombre de un usuario como clave y su mail como valor.Crear una función que almacene la clave y su mail siempre y cuando no haya otro nombre de usuario igual en el diccionario

def sumarusuario(dic,usu,valor): if not dic.has_key(usu): dic[usu]=valor

diccionario={}sumarusuario(diccionario,'juan','[email protected]')sumarusuario(diccionario,'ana','[email protected]')sumarusuario(diccionario,'luis','[email protected]')sumarusuario(diccionario,'luis','[email protected]')print diccionario

Resultado:{'luis': '[email protected]', 'juan': '[email protected]', 'ana': '[email protected]'}

Problema Propuesto

Crear un diccionario con 3 elementos (almacenar como clave el nombre de una fruta y como valor su precio). Luego hacer las siguientes operaciones:- Agregar un cuarto elemento.- Imprimer la cantidad de elementos del diccionario.- Borrar un elemento del diccionario.- Imprimir todas las claves.- Imprimir todos los valores.

Page 78: Manual Phyton

- Imprimir claves y valores.- Borrar el diccionario.

Ver soluciónfrutas={'manzanas':1.60,'peras':1.90,'bananas':0.95}print frutasprint ''frutas['naranjas']=2.50print len(frutas)print '<br>'del frutas['naranjas']for x in frutas.keys(): print xprint '<br>'for x in frutas.values(): print xprint '<br>'for (clave,valor) in frutas.items(): print clave+' '+str(valor)+' - 'print '<br>'frutas.clear()print frutas

Instalación de Python en su computadora

Ahora a llegado el momento de instalar Python en su equipo. Debemos descargar el instalador del sitio oficial de Python.

Aquí seguiremos los pasos para instalar la versión para Windows python-2.5.2. Descarguemos la versión para el procesasor x86.

Tenemos en nuestro equipo el archivo para hacer la instalación local de Python python-2.5.2.msi. Lo ejecutamos

El primer diálogo nos pregunta si se instala solo para nosotros o para todos los usuarios del equipo (podemos dejar la opción seleccionada para todos los usuarios) y presionamos 'Next'.

El segundo formulario del wizard nos permite seleccionar la unidad donde se instala el lenguaje. Dejemos por defecto la que nos propone el instalador: c:\Python25\

El tercer paso nos permite seleccionar o suprimir distintos módulos que vienen con Python (extensiones, documentación etc.), dejaremos por defecto que instale todos.

Finalmente ya tenemos instalado el lenguaje Python en nuestro equipo.

Ahora para codificar los programas utilizaremos un editor que se instala junto con el lenguaje Python, desde el menú de opciones podemos acceder al editor llamado: IDLE.

En realidad lo primero que aparece es una ventana llamada Python Shell donde podemos ejecutar instrucciones en forma unitaria:

Por ejemplo escribamos:

print 'Hola Mundo'

Page 79: Manual Phyton

Pero nuestro objetivo fundamental es la creación de programas o módulos completos en Python, para esto seleccionamos en esta ventana desde el menú de opciones File -> New Window.

Ahora sí tenemos el editor que suministra Python para codificar nuestros programas.

Escribamos una aplicación muy sencilla:

import random

def mostrarnumeros(): for x in range(7): valor=random.randint(1,100) print valor

mostrarnumeros()

La grabamos en nuestro disco duro (por ejemplo prueba1.py) y desde el menú de opciones seleccionamos Run -> Run Module, si hemos tipeado correctamente el programa tendremos el resultado en la ventana "Python Shell".

En los conceptos siguientes veremos temas que no pueden ser ejecutados directamente en el sitio PythonYa, por lo que tener el lenguaje Python en forma local en su equipo se hace indispensable para probarlos.

Creación, carga y lectura de archivos de texto

Python cuenta con una clase llamada file que nos permite crear, escribir y leer datos de un archivo de texto.

Para crear un objeto de la clase file debemos utilizar la función open. Cuando llamamos a dicha función le pasamos como primer parámetro el nombre del archivo de texto y el modo de apertura del mismo:

open(nombre del archivo,modo)

Si el archivo de texto se encuentra en la misma carpeta que nuestro programa no necesitamos indicar el path (camino). Los modos de apertura del archivo de texto pueden ser:

'r' Abre el archivo para lectura (debe existir el archivo) 'w' Crea el archivo y lo abre para escribir 'a' Abre el archivo para escribir. Se crea si el archivo no existe. Solo podemos agregar datos al final

Creación de un archivo de texto

El siguiente algoritmo crea en disco un archivo de texto llamado 'datos.txt' y no graba datos. Si queremos luego de ejecutar el programa podemos verificar la existencia del archivo en la misma carpeta donde almacenamos nuestro programa.

Cuando lo grabamos el archivo fuente en Python debemos darle un nombre al programa (por ejemplo texto1.py)

def creaciontxt(): archi=open('datos.txt','w') archi.close()

creaciontxt()

Creamos una función llamada creaciontxt donde primero llamamos a la función open pasando como parámetros el nombre del archivo de texto a crear y el modo de apertura ('w')

Page 80: Manual Phyton

La función open retorna la referencia del objeto file. Luego llamamos al método close de la clase file. Si luego queremos ver si se a creado el archivo de textos podemos hacerlo desde algun explorador de archivos, en la carpeta donde se encuentra nuestro programa en Python veremos un archivo llamado 'datos.txt' que tiene un tamaño de 0 bytes.

Grabación de líneas en el archivo de texto

def creartxt(): archi=open('datos.txt','w') archi.close()

def grabartxt(): archi=open('datos.txt','a') archi.write('Linea 1\n') archi.write('Linea 2\n') archi.write('Linea 3\n') archi.close()

creartxt()grabartxt()

La función creartxt es similar al ejemplo anterior, y la función grabartxt tiene por objetivo abrir el archivo en modo de agregado. Cada vez que grabamos un string en el archivo de texto insertamos un salto de línea '\n'. Finalmente liberamos el archivo llamando al método close.

Para ver el contenido de nuestro archivo de texto debemos utilizar un editor de texto (bloc de notas o el mismo entorno del Idle nos puede servir para ver el contenido de un archivo txt)

Lectura línea a línea de un archivo de texto

La clase file tiene un método llamado readline() que retorna toda una línea del archivo de texto y deja posicionado el puntero de archivo en la siguiente línea. Cuando llega al final del archivo readline retorna un string vacío.

def creartxt(): archi=open('datos.txt','w') archi.close()

def grabartxt(): archi=open('datos.txt','a') archi.write('Linea 1\n') archi.write('Linea 2\n') archi.write('Linea 3\n') archi.close()

def leertxt(): archi=open('datos.txt','r') linea=archi.readline() while linea!="": print linea linea=archi.readline() archi.close()

creartxt()grabartxt()leertxt()

Luego de de abrir el archivo para lectura procedemos a leer la primer línea:

archi=open('datos.txt','r') linea=archi.readline()

Page 81: Manual Phyton

El while se repite mientras el método readline() no retorne un string vacío. Dentro del while procedemos a imprimir la línea que acabamos de leer y leemos la siguiente (el método readline() retorna el contenido de toda la línea inclusive el salto de línea \n):

while linea!="": print linea linea=archi.readline()

Podemos leer todo el contenido de un archivo de texto y almacenarlo en una lista (esto tiene sentido si el archivo de texto no es muy grande):

def creartxt(): archi=open('datos.txt','w') archi.close()

def grabartxt(): archi=open('datos.txt','a') archi.write('Linea 1\n') archi.write('Linea 2\n') archi.write('Linea 3\n') archi.close()

def leertxtenlista(): archi=open('datos.txt','r') lineas=archi.readlines() print lineas archi.close()

creartxt()grabartxt()leertxtenlista()

Utilizamos el método readlines() en lugar de readline(). El método readlines() retorna una lista con cada línea del archivo de texto.

Recordemos que podemos procesar luego cada elemento de la lista recorriéndola con una estructura repetitiva:

def leertxtenlista(): archi=open('datos.txt','r') lineas=archi.readlines() for li in lineas: print li archi.close()

Captura de excepciones

Cuando nuestra aplicación genera un error que Python no puede resolver podemos disponer un código que se ejecute para dichas situaciones.

Errores como tratar de abrir un archivo que no existe, acceder a un elemento de una lista que no existe, dividir por cero etc. genera un error que hace que nuestro programa se detenga y no continúe su ejecución. Pero con Python podemos preveer estas situaciones y definir un algoritmo que se ejecutará exepcionalmente cuando ocurra dicho error.

Si ejecutamos el siguiente código el programa se detendrá informándonos que se produjo un error y no puede continuar:

y=0x=10/y

Page 82: Manual Phyton

print 'esta linea nunca se ejecuta'

Utilizando excepciones podemos capturar el error y continuar la ejecución del programa:

y=0try: x=10/yexcept ZeroDivisionError: print 'No existe la division por cero'print 'Esta linea si se ejecuta'

La estructura try/except requiere que indiquemos el tipo de excepción a capturar, en este caso cuando se trata de dividir por cero Python genera una excepción llamada ZeroDivisionError. Para capturar dicha excepción debemos disponerla seguido de la palabra clave except.

Si se produce la excepción se ejecutan las instrucciones que dispongamos en las líneas siguientes al except.

Cuando se captura una excepción el programa no se detiene y continua con las intrucciones siguientes al bloque try/except.

Veamos otro ejemplo de intentar acceder a un elemento que no existe en una lista:

lista1=['juan','ana','carlos']try: print lista1[5]except IndexError: print 'Intenta acceder a un elemento no existente a la lista'

lista1 almacena 3 elementos y tratamos de acceder al de la posición 5. Python en este situación genera una excepción de tipo IndexError, como disponemos el acceso dentro de la contrucción try/except y captura el tipo de excepción IndexError el programa no se detiene y ejecuta la instrucción seguida de la línea except IndexError.

Un tema de aplicación muy común donde se utilizan las excepciones es con el tratamiento de archivos, hay muchas situaciones que pueden generar excepciones en estos casos como puede ser que no se pueda abrir un archivo porque no existe, no lo pueda crear porque la unidad de amacenamiento está llena, el archivo se encuentra bloqueado por otro programa etc.

El código para crear, grabar y leer un archivo capturando las excepciones queda de la siguiente manera:

def creartxt(): try: archi=open('datos.txt','w') archi.close() except IOError: print 'No se pudo crear el archivo'

def grabartxt(): try: archi=open('datos.txt','a') archi.write('Linea 1\n') archi.write('Linea 2\n') archi.write('Linea 3\n') archi.close() except IOError: print 'No se pudo abrir el archivo'

def leertxt(): try: archi=open('noexiste.txt','r') linea=archi.readline()

Page 83: Manual Phyton

while linea!="": print linea linea=archi.readline() archi.close() except IOError: print 'El archivo no existe'

creartxt()grabartxt()leertxt()

La excepción cumple un doble cometido en estas situaciones, primero mostramos mensajes que nosotros definimos y no los que Python muestra por defecto cuando se genera un error y por otro lado podemos continuar con la ejecución de nuestro algoritmo sin que se detenga.

Podemos disponer varios capturas de excepciones para un bloque try:

lista1=['juan','ana','carlos']try: print lista1[0] z=10/0except IndexError: print 'Intenta acceder a un elemento no existente a la lista'except ZeroDivisionError: print 'Division por cero no permitida'

En este bloque try capturamos las excepciones de tipo: IndexError y ZeroDivisionError. Como podemos ver la que se dispara es la de ZeroDivisionError. Pero podemos generar el otro tipo de excepción modificando la línea de impresión del elemento de la lista:

print lista1[5]

Si hacemos este cambio se ejecuta la sección seguida a 'except IndexError:'. Una vez disparada dicha excepción no continua con las instrucciones del bloque del try, es decir no generará la excepción de división por cero, pero si continuará con el flujo del algoritmo.

Si no queremos tratar los errores en forma independiente podemos agrupar excepciones:

lista1=['juan','ana','carlos']try: print lista1[0] z=10/0except (IndexError,ZeroDivisionError): print 'Se produjo un error'

Debemos indicar entre paréntesis todas las excepciones a capturar y como se procede con ellas, en este caso solo se muestra un mensaje 'Se produjo un error'.

Otra parte opcional de un bloque try es la del else. Este bloque se ejecuta si no se produce la excepción:

lista1=['juan','ana','carlos']try: print lista1[0] z=10/5except (IndexError,ZeroDivisionError): print 'Se produjo un error'else: print z

Este programa muestra el primer elemento de la lista, luego procede a inicializar la variable z con el valor 10/5 y seguidamente ejecuta la sección del else ya que no se a generado excepciones.

Page 84: Manual Phyton

Podemos tratar de imprimir una componente que no exista de la lista y veremos que no se ejecuta el bloque del else.

Hemos visto que podemos capturar distintas excepciones en forma independiente:

except IndexError: print 'Intenta acceder a un elemento no existente a la lista'except ZeroDivisionError: print 'Division por cero no permitida'

En forma conjunta:

except (IndexError,ZeroDivisionError): print 'Se produjo un error'

Inclusive Python nos permite disponer un bloque try except para la captura de cualquier tipo de excepción (si bien esto no es lo más recomendable ya que es difícil emprender una acción para todos los tipos de errores que pueden generarse):

lista1=['juan','ana','carlos']try: print lista1[0] z=10/0except: print 'Se produjo un error'

Otra sección que puede tener un bloque try except es finally.

finally permite disponer un bloque de código que se ejecutará siempre, indistintamente se produzca o no la excepción. El objetivo de esta sección es generalmente utilizado para liberar recursos como puede ser cerrar la conexión con una base de datos o cerrar un archivo.

try: z=10/0 print 'Esto no se ejecuta'except: print 'Se produjo un error'finally: print 'Siempre se ejecuta'

Problema resuelto

Definir una diccionario donde se debe almacenar los nombres de frutas como clave y su precio como valor. Tratar de acceder a una clave inexistente y capturar la excepción KeyError que se produce en estos casos.

frutas={'naranjas':1.5,'manzanas':2.3,'peras':1.5}try: print frutas['sandias'] except KeyError: print 'No existe dicha fruta'

Resultado:No existe dicha fruta

Page 85: Manual Phyton

Google App Engine utilizando Python

El servicio de Google App Engine nos permite obtener una cuenta para crear nuestras aplicaciones web utilizando los servidores y tecnología de Google. Y como ventaja después de haber estudiado Python Google App Engine nos facilita crear un sitio utilizando como lenguaje de servidor el Python.

Actualmente nos suministra 500 MB para el almacenamiento de nuestras páginas y base de datos, todo esto en forma gratuita.

El primer paso es registrarnos en Google para obtener una cuenta y esto lo podemos hacer desde aquí Si tarda un poco la asignación de la cuenta no es tan importante ya que todo el desarrollo lo hacemos

en forma local en nuestro equipo. Finalizado el proyecto lo debemos cargar en los servidores de Google.

Para trabajar en forma local debemos tener instalado el lenguaje Python en su versión 2.5 o superior.

También tenemos que tener instalado el kid de desarrollo que nos provee Google y ejecuta nuestra aplicación en forma local, podemos descargar la última actualización del mismo desde aquí.

Luego de instalar el Python 2.5 o superior debemos proceder a instalar el kid de desarrollo que nos provee Google. Cuando lo instalamos nos sugiere donde se instala el software (podemos dejar el que nos propone por defecto): c:\Archivo de programa\Google\google_appengine\

Ya tenemos todo para comenzar a experimentar con Python y el framework que nos provee Google para el desarrollo de aplicaciones web.

Si ya dispone la cuenta suministrada por Google desde el panel de administración podemos crear una aplicación presionando el botón "Create an Application".

Debemos seleccionar un nombre para nuestra aplicación que correrá como un subdominio de appspot.com, como podrán comprobar muchos de los nombres más comunes ya han sido tomados por otros usuarios.

Seleccionado un nombre disponible (podemos comprobar disponibilidad presionando el botón "Check Availability") asignamos un título y aceptamos los términos del servicio. Ya estamos en condiciones de subir nuestra aplicación (tengamos en cuenta que todavía no hemos desarrollado ni el 'Hola Mundo')

Hola mundo con Google App Engine

Primero debemos crear un directorio donde se instaló el Google App Engine, normalmente en: c:\Archivo de programa\Google\google_appengine\

Este nombre debe coincidir con el que obtuvimos desde el panel de control de nuestra cuenta de Google App Engine (yo tomaré como nombre tutorialya)

Para utilizar los servidores de Google deberemos crear un archivo de configuración llamado app.yaml y que deberemos localizar en el directorio que acabamos de crear.

El archivo app.yaml tiene una estructura similar a:

application: tutorialyaversion: 1runtime: pythonapi_version: 1

Page 86: Manual Phyton

handlers:- url: /.* script: tutorialya.py

Del ejemplo anterior deberá modificar la propiedad de application con el nombre de aplicación que gestionó desde su panel de control del Google App Engine. Lo mismo pasa con la propiedad script.

Ahora que tenemos nuestro directorio donde se alojará nuestro sitio en forma local y el archivo de configuración app.yaml debemos crear el archivo Python principal y lo llamaremos igual que el nombre de la carpeta y con extensión *.py y debe coincidir con la propiedad script del archivo app.yaml (en mi caso yo lo llamé tutorialya.py).

Para codificar nuestra aplicación Google creó un framework propio llamado webapp y que se instala automáticamente con nuestra aplicación.

Luego nuestra aplicación mínima utilizando dicho framework es:

import wsgiref.handlers

from google.appengine.ext import webapp

class HolaMundo(webapp.RequestHandler): def get(self): self.response.out.write('<html><head></head>') self.response.out.write('<body>') self.response.out.write('<h1>Hola Mundo</h1>') self.response.out.write('</body>')

def main(): application = webapp.WSGIApplication([('/', HolaMundo)], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

Después nos detendremos en la forma de codificar utilizando este framework, por ahora solo nos interesa ver aparecer el 'Hola mundo' en el navegador.

Ya tenemos codificado el archivo *.yaml y *.py, ahora queda iniciar nuestro servidor y peticionar la página.

Como servidor web no utilizaremos el Apache, sino un servidor creado con Python que viene incluido con el Google App Engine. Para activar este servidor debemos ir a la línea de comandos de nuestro sistema operativo hasta la carpeta (c:\Archivo de programa\Google\google_appengine\) y desde allí arrancar el servidor indicando el nombre de nuestra aplicación:

c:\Archivo de programa\Google\google_appengine>dev_appserver.py tutorialya/

Tener en cuenta de pasar como parámetro al programa dev_appserver.py el nombre de la carpeta que hemos creado para nuestro proyecto (en mi caso la llamé tutorialya)

Si tenemos correctamente creado el archivo *.yaml deberá mostrar un mensaje que el servidor web está esperando peticiones en el puerto 8080. Luego desde el navegador debemos llamar nuestra aplicación con la siguiente sintaxis:

http://localhost:8080

Si codificamos correctamente la aplicación deberemos tener el mensaje 'Hola Mundo'.

Page 87: Manual Phyton

Subir nuestra aplicación Hola mundo a internet

Si ya tenemos nuestra aplicación ejecutándose en forma correcta localmente:

http://localhost:8080

Ahora para que la puedan acceder todos en internet debemos seguir los siguientes pasos:

El primer paso es registrarnos en Google si todavía no lo hemos hecho para obtener una cuenta y esto lo podemos hacer desde aquí

Si ya dispone la cuenta suministrada por Google desde el panel de administración podemos crear una aplicación presionando el botón "Create an Application".

Debemos seleccionar un nombre para nuestra aplicación que correrá como un subdominio de appspot.com.

Seleccionado un nombre disponible (podemos comprobar disponibilidad presionando el botón "Check Availability") asignamos un título y aceptamos los términos del servicio. Ya estamos en condiciones de subir nuestra aplicación

Controlar que nuestro archivo app.yaml tiene una estructura similar a: application: tutorialya version: 1 runtime: python api_version: 1 handlers: - url: /.* script: tutorialya.py

Del ejemplo anterior deberá modificar la propiedad de application con el nombre de aplicación que gestionó desde su panel de control del Google App Engine. Lo mismo pasa con la propiedad script.

Desde la línea de comandos del sistema operativo ejecutar el siguiente programa en Python que tiene por objetivo hacer el upload de todo nuestro proyecto a la cuenta que tenemos asignada en Google App Engine:

c:\Archivo de programa\Google\google_appengine>appcfg.py update tutorialya/

En ese momento se nos solicitará nuestro mail y clave.

Ya tenemos en el servidor almacenado nuestro sitio, solo nos falta llamarlo para verlo correr en la web.

http://tutorialya.appspot.com/

Recordar de remplazar el nombre tutorialya con el nombre con el que crearon su aplicación desde el panel del Google App Engine.

Recuperar el dato de un text (App Engine)

Realizaremos una aplicación que muestre un formulario con un control de tipo text y cuando se presione el botón submit mostraremos el dato ingresado en otra página.

import cgi

Page 88: Manual Phyton

import wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form method="post" action="procformulario1">Ingrese su nombre:<input type="text" name="nombre" size="20"><br><input type="submit" value="Ok"></form></body>""")

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") self.response.out.write(cgi.escape(self.request.get('nombre'))) self.response.out.write("</body></body>")

def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1)], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

El programa se inicia al ser verdadera la condición:

if __name__ == '__main__': main()

Los módulos son objetos y todos los módulos tienen un atributo llamado __name__. El valor del __name__ de un módulo depende de cómo esté usándolo. Si se importa el módulo, luego la propiedad __name__ es el nombre del fichero del módulo, sin el directorio de la ruta ni la extensión del archivo. Pero también puede ejecutar el módulo directamente como si fuera un programa, en cuyo caso __name__ tendrá un valor especial predefinido __main__.

El if se verifica como verdadero y llama a la función main().

En la función main debemos crear un objeto de la clase WSGIApplication y pasar como parámetro una lista con elementos de tipo tupla que asocian una URL y la clase que procesa dicha petición.

Cuando hacemos referencia a la raiz de nuestro sitio:

http://localhost:8080/

El servidor ejecuta Formulario1 según la tupla indicada con: ('/', Formulario1)

De forma similar cuando se presiona el botón submit del formulario se llama:

http://localhost:8080/procformulario1

y mediante la asociación ('/procformulario1', ProcFormulario1) se ejecutará el código de la clase ProcFormulario.

Page 89: Manual Phyton

Todas las páginas de nuestro sitio deben ser mapeadas en la lista:

application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1)], debug=True)

El segundo parámetro del constructor de la clase WSGIApplication es el modo de ejecución, normalmente el parámetro debug lo inicializamos en true mientras estamos depurando nuestra aplicación, cuando la finalizamos y la subimos al servidor el parámetro debug le asignamos False.

La clase WSGIApplication se encuentra en el módulo webapp que se encuentra en el paquete google.appengine.ext:

from google.appengine.ext import webapp

La clase Formulario1 hereda de la clase RequestHandler que se encuentra en el paquete webapp. Para generar la página solo debemos reescribir el método get que será el que genere la página web. Para generar el contenido de la página llamamos al método write. La clase RequestHandler contiene un atributo llamado response y este un atributo out que es el que contiene el método write, es decir cada vez que queremos imprimir en la página debemos disponer el siguiente código:

self.response.out.write("Hola Mundo")

Si se trata de generar un bloque grande de HTML podemos utilizar la característica de Python de definir un String de varias líneas encerrándolas entre triple comillas:

self.response.out.write("""<html><head></head><body><form method="post" action="procformulario1">Ingrese su nombre:<input type="text" name="nombre" size="20"><br><input type="submit" value="Ok"></form></body>""")

Como vemos no es necesario escapar con el caracter '\' las comillas dobles cuando usamos triple comillas.

Podemos llamar tantas veces al método write como se necesite, todos los string se almacenan en un archivo de memoria que es el que se enviará al navegador que hizo la petición.

Una vez que la página que contiene el formulario se muestra en el navegador el operador ingresa el nombre y al presionar el botón submit el navegador procede a enviar el dato ingresado al servidor.

En la propiedad action del formulario hemos indicado quien procesará el dato en el servidor:

action="\procformulario1\"

Recordemos que tenemos mapeada dicha url :

application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1)], debug=True)

Es decir que la clase ProcFormulario1 recibe el dato. Esta clase también hereda de RequestHandler pero debe redefinir el método post. Luego procedemos de forma similar a la otra clase para crear una página en

Page 90: Manual Phyton

forma dinámica llamando al método write, con la salvedad que para recuperar el dato cargado en el formulario procedemos a llamar al método get del objeto request que contiene la clase:

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") self.response.out.write(cgi.escape(self.request.get('nombre'))) self.response.out.write("</body></body>")

Formulario HTML - control radio (App Engine)

Realizaremos una aplicación que muestre un formulario con dos controles de tipo text, luego dos controles de tipo radio que indiquen si queremos sumar o restar los valores ingresados en los controles text.

import cgiimport wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="procformulario1" method="post">Ingrese primer valor:<input type="text" name="valor1"><br>Ingrese segundo valor:<input type="text" name="valor2"><br><input type="radio" name="radio1" value="suma">sumar<br><input type="radio" name="radio1" value="resta">restar<br><input type="submit" value="operar"></form></body></html> """)

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") v1=int(self.request.get('valor1')) v2=int(self.request.get('valor2')) operacion=self.request.get('radio1') if operacion=="suma": resultado=v1+v2 else: resultado=v1-v2 self.response.out.write("El resultado de la " + operacion + " es " + str(resultado)) self.response.out.write("</body></body>")

def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1)], debug=True) wsgiref.handlers.CGIHandler().run(application)

Page 91: Manual Phyton

if __name__ == '__main__': main()

En la página principal del sitio asociamos la clase que despliega el formulario HTML:

('/', Formulario1)

Luego la clase que procesa los datos ingresados en el formulario es ProcFormulario1, en esta primero rescatamos los dos valores ingresados en los controles text y procedemos a convertilos a entero:

v1=int(self.request.get('valor1')) v2=int(self.request.get('valor2'))

Rescatamos la propiedad value del control radio seleccionado:

operacion=self.request.get('radio1')

Y mediante un if verificamos si tenemos que sumar o restar los contenidos de los text:

if operacion=="suma": resultado=v1+v2 else: resultado=v1-v2

Por último procedemos a imprimir el resultado de la operación:

self.response.out.write("El resultado de la " + operacion + " es " + str(resultado))

Formulario HTML - control select (App Engine)

Veamos el control HTML de tipo select. Este tipo de control el funcionamiento es similar al de un conjunto de controles de tipo radio.

Confeccionaremos el mismo problemas del concepto anterior es decir cargar dos números y posteriormente mediante un control de tipo select seleccionar si queremos sumarlos o restarlos (solo una de estas operaciones se puede elegir)

La sintaxis del control de tipo select es:

<select name="operacion"><option value="suma">Sumar</option><option value="resta">Restar</option></select>

Es importante notar que la sintaxis es bastante distinta a los controles de tipo text y radio.

El elemento select tiene definido la propiedad name mediante la cual rescataremos el valor seleccionado en el servidor.

El elemento select contiene un conjunto de elementos option. Cada elemento option tiene definido la propiedad value. El que quede seleccionado el control select rescata su propiedad value.

Luego el programa en Python utilizando Google App Engine:

import cgiimport wsgiref.handlers

Page 92: Manual Phyton

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="procformulario1" method="post">Ingrese primer valor:<input type="text" name="valor1"><br>Ingrese segundo valor:<input type="text" name="valor2"><br><select name="operacion"><option value="suma">Sumar</option><option value="resta">Restar</option></select><br><input type="submit" value="operar"></form></body></html>""")

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") v1=int(self.request.get('valor1')) v2=int(self.request.get('valor2')) op=self.request.get('operacion') if op=="suma": resultado=v1+v2 else: resultado=v1-v2 self.response.out.write("El resultado de la " + op + " es " + str(resultado)) self.response.out.write("</body></body>")

def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1)], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

De forma similar como venimos trabajando en una clase desplegamos el formulario HTML (Formulario1) y otra clase procesa el contenido del formulario (ProcFormulario1).

En la página que procesamos los datos del formulario rescatamos los valores de los controles text y los convertimos a entero:

v1=int(self.request.get('valor1')) v2=int(self.request.get('valor2'))

Seguidamente rescatamos la propiedad name de la opción seleccionada del control select:

op=self.request.get('operacion')

Mediante un if verificamos si tenemos que sumar o restar:

Page 93: Manual Phyton

if op=="suma": resultado=v1+v2 else: resultado=v1-v2

Por último mostramos el resultado:

self.response.out.write("El resultado de la " + op + " es " + str(resultado))

Formulario HTML - control select con selección múltiple (App Engine)

Veamos una variante del control select la cual permite seleccionar varias opciones de su contenido. Para esto debemos agregar la propiedad multiple cuando lo definimos:

<select name="operacion" multiple>

Con este simple cambio podemos seleccionar más de un elemento del interior del control select.

Confeccionaremos el mismo problema anterior, solo que ahora podremos seleccionar las dos operaciones en forma simultanea:

import cgiimport wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="procformulario1" method="post">Ingrese primer valor:<input type="text" name="valor1"><br>Ingrese segundo valor:<input type="text" name="valor2"><br><select name="operacion" multiple><option value="suma">Sumar</option><option value="resta">Restar</option></select><br><input type="submit" value="operar"></form></body></html>""")

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") v1=int(self.request.get('valor1')) v2=int(self.request.get('valor2')) operaciones=self.request.get_all('operacion') for op in operaciones: if op=="suma": resultado=v1+v2 self.response.out.write("El resultado de la " + op + " es " + str(resultado) + "<br>") if op=="resta": resultado=v1-v2

Page 94: Manual Phyton

self.response.out.write("El resultado de la " + op + " es " + str(resultado) + "<br>") self.response.out.write("</body></body>")

def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1)], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

Para recuperar la lista de valores seleccionados del control select debemos llamar al método get_all del objeto request en lugar de get:

operaciones=self.request.get_all('operacion')

Luego mediante una estructura repetitiva recorremos la lista de valores devuelto y comparamos con los valores posibles:

for op in operaciones: if op=="suma": resultado=v1+v2 self.response.out.write("El resultado de la " + op + " es " + str(resultado) + "<br>") if op=="resta": resultado=v1-v2 self.response.out.write("El resultado de la " + op + " es " + str(resultado) + "<br>")

Formulario HTML - control checkbox (App Engine)

Otra forma de hacer selecciones múltiples es utilizar un conjunto de controles de tipo checkbox. Cada control de tipo checkbox es independiente.

Resolvamos el problema del concepto anterior empleando dos controles de tipo checkbox:

import cgiimport wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="procformulario1" method="post">Ingrese primer valor:<input type="text" name="valor1"><br>Ingrese segundo valor:<input type="text" name="valor2"><br><input type="checkbox" name="check1" value="suma">sumar<br><input type="checkbox" name="check2" value="resta">restar<br><input type="submit" value="operar">

Page 95: Manual Phyton

</form></body></html>""")

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") v1=int(self.request.get('valor1')) v2=int(self.request.get('valor2')) su=self.request.get('check1') if su=="suma": resultado=v1+v2 self.response.out.write("El resultado de la " + su + " es " + str(resultado) + "<br>") re=self.request.get('check2') if re=="resta": resultado=v1-v2 self.response.out.write("El resultado de la " + re + " es " + str(resultado) + "<br>") self.response.out.write("</body></body>")

def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1)], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

Cada checkbox lo recuperamos en forma independiente:

su=self.request.get('check1') if su=="suma": resultado=v1+v2 self.response.out.write("El resultado de la " + su + " es " + str(resultado) + "<br>")

Si se encuentra seleccionado el método get retorna el valor de la propiedad value del control HTML, en caso de no estar seleccionado retorna un string vacío.

Formulario HTML - control textarea (App Engine)

Otro control de uso común es el textarea, a diferencia de un control de tipo "text" nos permite ingresar muchas líneas de texto.

Confeccionaremos una página que solicite el ingreso del nombre de una persona y en un control de tipo textarea permitiremos ingresar un comentario. En la página que procesa los datos mostraremos los datos cargados en los dos controles:

import cgiimport wsgiref.handlers

from google.appengine.ext import webapp

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head>

Page 96: Manual Phyton

<body><form action="procformulario1" method="post">Ingrese su nombre:<input type="text" name="nombre"><br>Comentarios<br><textarea name="comentarios" rows="10" cols="40"></textarea><br><input type="submit" value="enviar"><br></form></body></html>""")

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) self.response.out.write("Nombre:"+ nom + "<br>") com=cgi.escape(self.request.get('comentarios')) self.response.out.write("Comentarios:"+ com + "<br>") self.response.out.write("</body></body>")

def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1)], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

La función escape del módulo cgi tiene por objetivo convertir a entidades los caracteres <, > etc., con esto si se ingresa una marca HTML esta se mostrará y no la interpretará el navegador.

Recuperamos cada dato y lo mostramos en la página HTML:

nom=cgi.escape(self.request.get('nombre')) self.response.out.write("Nombre:"+ nom + "<br>") com=cgi.escape(self.request.get('comentarios')) self.response.out.write("Comentarios:"+ com + "<br>")

Alta y listado de una base de datos (App Engine)

El almacenamiento de datos utilizando la infraestructura de Google es bastante distinta a las metodologías de MySql, Oracle, Sql Server etc.

Google utiliza una tecnología llamada 'Bigtable', básicamente es un sistema de almacenamiento distribuido que permite escalar de forma muy sencilla, evitando que por ejemplo las consultas de tablas con millones de registros se resientan.

Para hacer uso de esta tecnología debemos importar el paquete db:

from google.appengine.ext import db

Desarrollaremos una aplicación que permita almacenar el nombre de usuario y su clave. Luego imprimiremos todos los registros almacenados.

import cgiimport wsgiref.handlers

Page 97: Manual Phyton

from google.appengine.ext import webappfrom google.appengine.ext import db

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="procformulario1" method="post">Ingrese su nombre:<input type="text" name="nombre"><br>Ingrese su clave:<input type="password" name="clave"><br><input type="submit" value="enviar"><br></form></body></html>""")

class TablaUsuarios(db.Model): nombre=db.StringProperty() clave=db.StringProperty()

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) cla=cgi.escape(self.request.get('clave')) usuario=TablaUsuarios() usuario.nombre=nom usuario.clave=cla usuario.put() self.response.out.write("<a href=\"listadousuarios\">Listado</a>") self.response.out.write("</body></body>") class ListadoUsuarios(webapp.RequestHandler): def get(self): self.response.out.write("<html><head></head><body>") usuarios=db.GqlQuery("select * from TablaUsuarios") for usu in usuarios: self.response.out.write("Nombre:" + usu.nombre +"<br>") self.response.out.write("Clave:" + usu.clave +"<br>") self.response.out.write("<hr>") self.response.out.write("<a href=\"\\\">Principal</a>") self.response.out.write("</body></body>")

def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1), ('/listadousuarios', ListadoUsuarios)], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

Veamos todo lo que debemos agregar:

Debemos importar el paquete db: from google.appengine.ext import db

Page 98: Manual Phyton

Debemos declarar una clase que representa una tabla. Esta clase debe heredar de la clase Model contenida en el paquete db. Definimos dos atributos de tipo StringProperty. StringProperty es una clase contenida en el paquete db y que encapsula el manejo de un campo de cadena de caracteres:

class TablaUsuarios(db.Model): nombre=db.StringProperty() clave=db.StringProperty()

Para efectuar el alta de un registro en la tabla: class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) cla=cgi.escape(self.request.get('clave')) usuario=TablaUsuarios() usuario.nombre=nom usuario.clave=cla usuario.put() self.response.out.write("<a href=\"listadousuarios\">Listado</a>") self.response.out.write("</body></body>")

Creamos un objeto de la clase Tablausuarios:

usuario=TablaUsuarios()

Inicializamos los atributos nombre y clave con los datos extraidos del formulario.

usuario.nombre=nom usuario.clave=cla

Llamamos al método put que confirma los datos previamente cargados:

usuario.put()

Para obtener un listado de todos los registros almacenados: class ListadoUsuarios(webapp.RequestHandler): def get(self): self.response.out.write("<html><head></head><body>") usuarios=db.GqlQuery("select * from TablaUsuarios") for usu in usuarios: self.response.out.write("Nombre:" + usu.nombre +"<br>") self.response.out.write("Clave:" + usu.clave +"<br>") self.response.out.write("<hr>") self.response.out.write("<a href=\"\\\">Principal</a>") self.response.out.write("</body></body>")

Creamos un objeto de la clase GqlQuery pasando como parámetro al constructor los datos a recuperar:

usuarios=db.GqlQuery("select * from TablaUsuarios")

Mediante un for recorremos la lista de usuarios y los imprimimos:

for usu in usuarios: self.response.out.write("Nombre:" + usu.nombre +"<br>") self.response.out.write("Clave:" + usu.clave +"<br>") self.response.out.write("<hr>")

Como esta aplicación requiere tres páginas luego debemos registrarlas cuando creamos un objeto de la clase WSGIApplication:

def main(): application = webapp.WSGIApplication([('/', Formulario1),

Page 99: Manual Phyton

('/procformulario1', ProcFormulario1), ('/listadousuarios', ListadoUsuarios)], debug=True) wsgiref.handlers.CGIHandler().run(application)

Consulta de datos (App Engine)

Confeccionaremos una aplicación que nos permita ingresar el nombre de usuario y nos recupere y muestre su clave. Tener en cuenta los datos cargados en el concepto anterior.

import cgiimport wsgiref.handlers

from google.appengine.ext import webappfrom google.appengine.ext import db

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="procformulario1" method="post">Ingrese nombre de usuario:<input type="text" name="nombre"><br><input type="submit" value="enviar"><br></form></body></html>""")

class TablaUsuarios(db.Model): nombre=db.StringProperty() clave=db.StringProperty()

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: self.response.out.write("Clave:" + usu[0].clave +"<br>") else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("<a href=\"\\\">Principal</a>") self.response.out.write("</body></body>") def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1), ], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

Creamos un formulario para ingresar el nombre de usuario a buscar:

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""

Page 100: Manual Phyton

<html><head></head><body><form action="procformulario1" method="post">Ingrese nombre de usuario:<input type="text" name="nombre"><br><input type="submit" value="enviar"><br></form></body></html>""")

El botón submit hace que se ejecute la clase ProcFormulario1:

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: self.response.out.write("Clave:" + usu[0].clave +"<br>") else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("<a href=\"\\\">Principal</a>") self.response.out.write("</body></body>")

Primero generamos una consulta a la tabla y le pasamos como parámetro en el campo nombre el valor rescatado del formulario, debemos utilizar los dos puntos y un uno para indicar que dicho espacio será remplazado por el segundo parámetro:

usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom)

La clase GqlQuery tiene un método llamado fetch que retorna todos los registros generados en la consulta. Al método fetch le pasamos la cantidad de registros que queremos rescatar y por último accedemos a la primer componente de la lista siempre y cuando la cantidad de elementos sea mayor a cero.

Borrado de datos (App Engine)

Confeccionaremos una aplicación que nos permita ingresar el nombre de usuario y efectúe su borrado.. Tener en cuenta los datos cargados en conceptos anterioriores.

import cgiimport wsgiref.handlers

from google.appengine.ext import webappfrom google.appengine.ext import db

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="procformulario1" method="post">Ingrese nombre de usuario a borrar:<input type="text" name="nombre"><br><input type="submit" value="enviar"><br></form></body></html>""")

Page 101: Manual Phyton

class TablaUsuarios(db.Model): nombre=db.StringProperty() clave=db.StringProperty()

class ProcFormulario1(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: usu[0].delete() self.response.out.write("Se borro el usuario<br>") else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("<a href=\"\\\">Principal</a>") self.response.out.write("</body></body>") def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/procformulario1', ProcFormulario1), ], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

Si lo comparamos con la consulta es prácticamente igual con la salvedad donde en lugar de mostrarlo procedemos a borrarlo:

nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: usu[0].delete() self.response.out.write("Se borro el usuario<br>") else: self.response.out.write("No existe un usuario con dicho nombre<br>")

El método delete borrar el registro.

Modificación de datos (App Engine)

Trabajaremos nuevamente con el problema de usuarios. Dispondremos un formulario que solicite la carga del nombre de un usuario y pasaremos a un segundo formulario donde mostraremos los datos actuales de dicho usuario. En una tercer página procedemos a modificar los datos ingresados.

import cgiimport wsgiref.handlers

from google.appengine.ext import webappfrom google.appengine.ext import db

class Formulario1(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="formulario2" method="post">

Page 102: Manual Phyton

Ingrese nombre de usuario a modificar:<input type="text" name="nombre"><br><input type="submit" value="Buscar"><br></form></body></html>""")

class TablaUsuarios(db.Model): nombre=db.StringProperty() clave=db.StringProperty()

class Formulario2(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: self.response.out.write("""<html><head></head><body><form action="procformulario2" method="post">Nombre actual:""") self.response.out.write("<input type=\"text\" name=\"nombre\" value=\""+usu[0].nombre+"\"><br>") self.response.out.write("Clave actual:") self.response.out.write("<input type=\"text\" name=\"clave\" value=\""+usu[0].clave+"\"><br>") self.response.out.write("<input type=\"hidden\" name=\"nombreoculto\" value=\""+usu[0].nombre+"\">") self.response.out.write("""<input type="submit" value="Modificar"><br></form></body></html>""") else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("</body></body>")

class ProcFormulario2(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nomoculto=cgi.escape(self.request.get('nombreoculto')) nom=cgi.escape(self.request.get('nombre')) cla=cgi.escape(self.request.get('clave')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nomoculto) usu=usuario.fetch(1) if len(usu)>0: usu[0].nombre=nom usu[0].clave=cla usu[0].put() else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("<a href=\"\\\">Principal</a>") self.response.out.write("</body></body>") def main(): application = webapp.WSGIApplication([('/', Formulario1), ('/formulario2', Formulario2), ('/procformulario2', ProcFormulario2), ], debug=True)

Page 103: Manual Phyton

wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

El segundo formulario debemos inicializar los atributos value de los dos controles text para que aparezcan cargados inicialmente con los datos actuales.

Por otro lado también es necesario definir un campo oculto donde almacenar el nombre de usuario actual, ya que si lo modifica no sabremos cual buscar:

class Formulario2(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: self.response.out.write("""<html><head></head><body><form action="procformulario2" method="post">Nombre actual:""") self.response.out.write("<input type=\"text\" name=\"nombre\" value=\""+usu[0].nombre+"\"><br>") self.response.out.write("Clave actual:") self.response.out.write("<input type=\"text\" name=\"clave\" value=\""+usu[0].clave+"\"><br>") self.response.out.write("<input type=\"hidden\" name=\"nombreoculto\" value=\""+usu[0].nombre+"\">") self.response.out.write("""<input type="submit" value="Modificar"><br></form></body></html>""") else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("</body></body>")

La tercer página recupera el usuario que ingresó en el primer formulario, pero rescatado del campo oculto. Procedemos seguidamente a modificar los datos rescatados de la tabla y confirmamos los nuevos datos llamando al método put:

class ProcFormulario2(webapp.RequestHandler): def post(self): self.response.out.write("<html><head></head><body>") nomoculto=cgi.escape(self.request.get('nombreoculto')) nom=cgi.escape(self.request.get('nombre')) cla=cgi.escape(self.request.get('clave')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nomoculto) usu=usuario.fetch(1) if len(usu)>0: usu[0].nombre=nom usu[0].clave=cla usu[0].put() else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("<a href=\"\\\">Principal</a>") self.response.out.write("</body></body>")

Page 104: Manual Phyton

Listado, Alta, Baja y Modificación (App Engine)

Ahora plantearemos todos los conceptos vistos para el manejo de una tabla de datos utilizando el Google App Engine.

Mostraremos un listado con una tabla con todos los nombres de usuarios y claves, dos hipervínculos uno para poder borrar el usuario y otro para poder modificar el registro. Por último dispondremos un hipervínculo para llamar a un formulario de alta de usuario.

import cgiimport wsgiref.handlers

from google.appengine.ext import webappfrom google.appengine.ext import db

class TablaUsuarios(db.Model): nombre=db.StringProperty() clave=db.StringProperty()

class Listado(webapp.RequestHandler): def get(self): self.response.out.write("<html><head></head><body>") self.response.out.write("<table border=\"1\">") self.response.out.write("<tr>")

self.response.out.write("<td>Usuario</td><td>Clave</td><td>Borrar</td><td>Modificar&l

t;/td>") self.response.out.write("</tr>") usuarios=db.GqlQuery("select * from TablaUsuarios") for usu in usuarios: self.response.out.write("<tr>") self.response.out.write("<td>" + usu.nombre +"</td>") self.response.out.write("<td>" + usu.clave +"</td>") self.response.out.write("<td><a href=\"baja?nombre="+usu.nombre+"\">Borra?</a>"+"</td>") self.response.out.write("<td><a

href=\"formulariomodificacion?nombre="+usu.nombre+"\">Modifica?</a>"+"</td>") self.response.out.write("</tr>") self.response.out.write("<tr>") self.response.out.write("<td colspan=\"4\"><a href=\"formularioalta\">Alta</a></td>") self.response.out.write("</tr>") self.response.out.write("</table>") self.response.out.write("</body></html>")

class FormularioAlta(webapp.RequestHandler): def get(self): self.response.out.write("""<html><head></head><body><form action="alta" method="post">Ingrese su nombre:<input type="text" name="nombre"><br>Ingrese su clave:<input type="password" name="clave"><br><input type="submit" value="Alta"><br></form></body></html>""")

Page 105: Manual Phyton

class Alta(webapp.RequestHandler): def post(self): nom=cgi.escape(self.request.get('nombre')) cla=cgi.escape(self.request.get('clave')) usuario=TablaUsuarios() usuario.nombre=nom usuario.clave=cla usuario.put() self.redirect("/")

class Baja(webapp.RequestHandler): def get(self): nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: usu[0].delete() self.redirect("/") class FormularioModificacion(webapp.RequestHandler): def get(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: self.response.out.write("""<html><head></head><body><form action="modificacion" method="post">Nombre actual:""") self.response.out.write("<input type=\"text\" name=\"nombre\" value=\""+usu[0].nombre+"\"><br>") self.response.out.write("Clave actual:") self.response.out.write("<input type=\"text\" name=\"clave\" value=\""+usu[0].clave+"\"><br>") self.response.out.write("<input type=\"hidden\" name=\"nombreoculto\" value=\""+usu[0].nombre+"\">") self.response.out.write("""<input type="submit" value="Modificar"><br></form></body></html>""") else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("</body></body>") class Modificacion(webapp.RequestHandler): def post(self): nomoculto=cgi.escape(self.request.get('nombreoculto')) nom=cgi.escape(self.request.get('nombre')) cla=cgi.escape(self.request.get('clave')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nomoculto) usu=usuario.fetch(1) if len(usu)>0: usu[0].nombre=nom usu[0].clave=cla usu[0].put() self.redirect("/")

def main(): application = webapp.WSGIApplication([('/', Listado), ('/formularioalta',FormularioAlta ),

Page 106: Manual Phyton

('/alta',Alta ), ('/baja', Baja), ('/formulariomodificacion', FormularioModificacion), ('/modificacion', Modificacion), ], debug=True) wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__': main()

En la función main() debemos inicializar la lista que vincula las URL de las páginas y las clases que se ejecutan:

def main(): application = webapp.WSGIApplication([('/', Listado), ('/formularioalta',FormularioAlta ), ('/alta',Alta ), ('/baja', Baja), ('/formulariomodificacion', FormularioModificacion), ('/modificacion', Modificacion), ], debug=True) wsgiref.handlers.CGIHandler().run(application)

La clase Listado es la que muestra la raiz del sitio y tiene por objetivo crear una tabla HTML con todos los usuarios almacenados en la TablaUsuarios. Además de imprimir cada registro disponemos un hipervínculo pasando como parámetro el nombre de usuario a borrar o modificar:

class Listado(webapp.RequestHandler): def get(self): self.response.out.write("<html><head></head><body>") self.response.out.write("<table border=\"1\">") self.response.out.write("<tr>")

self.response.out.write("<td>Usuario</td><td>Clave</td><td>Borrar</td><td>Modificar&l

t;/td>") self.response.out.write("</tr>") usuarios=db.GqlQuery("select * from TablaUsuarios") for usu in usuarios: self.response.out.write("<tr>") self.response.out.write("<td>" + usu.nombre +"</td>") self.response.out.write("<td>" + usu.clave +"</td>") self.response.out.write("<td><a href=\"baja?nombre="+usu.nombre+"\">Borra?</a>"+"</td>") self.response.out.write("<td><a

href=\"formulariomodificacion?nombre="+usu.nombre+"\">Modifica?</a>"+"</td>") self.response.out.write("</tr>") self.response.out.write("<tr>") self.response.out.write("<td colspan=\"4\"><a href=\"formularioalta\">Alta</a></td>") self.response.out.write("</tr>") self.response.out.write("</table>") self.response.out.write("</body></html>")

La clase FormularioAlta muestra los dos controles text y el botón submit, cuando se presiona dicho botón se procede a llamar a la URL alta:

class FormularioAlta(webapp.RequestHandler):

Page 107: Manual Phyton

def get(self): self.response.out.write("""<html><head></head><body><form action="alta" method="post">Ingrese su nombre:<input type="text" name="nombre"><br>Ingrese su clave:<input type="password" name="clave"><br><input type="submit" value="Alta"><br></form></body></html>""")

La clase Alta inicializa un objeto de la clase TablaUsuarios, procede a registrar los datos y mediante el método redirect redirige a la raiz del sitio (es decir la clase Listado):

class Alta(webapp.RequestHandler): def post(self): nom=cgi.escape(self.request.get('nombre')) cla=cgi.escape(self.request.get('clave')) usuario=TablaUsuarios() usuario.nombre=nom usuario.clave=cla usuario.put() self.redirect("/")

Cuando se presiona el hipervínculo "Borra?" en el listado se ejecuta la clase Baja y recibe como parámetro en el hipervínculo el nombre de usuario a borrar. Recuperamos el registro, llamamos al método delete y redirigimos nuevamente a la página de listado:

class Baja(webapp.RequestHandler): def get(self): nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: usu[0].delete() self.redirect("/")

Cuando se presiona el hipervínculo "Modificación?" se ejecuta la clase FormularioModificacion, en este recuperamos el nombre de usuario e inicializamos los controles text y el campo oculto:

class FormularioModificacion(webapp.RequestHandler): def get(self): self.response.out.write("<html><head></head><body>") nom=cgi.escape(self.request.get('nombre')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nom) usu=usuario.fetch(1) if len(usu)>0: self.response.out.write("""<html><head></head><body><form action="modificacion" method="post">Nombre actual:""") self.response.out.write("<input type=\"text\" name=\"nombre\" value=\""+usu[0].nombre+"\"><br>") self.response.out.write("Clave actual:") self.response.out.write("<input type=\"text\" name=\"clave\" value=\""+usu[0].clave+"\"><br>")

Page 108: Manual Phyton

self.response.out.write("<input type=\"hidden\" name=\"nombreoculto\" value=\""+usu[0].nombre+"\">") self.response.out.write("""<input type="submit" value="Modificar"><br></form></body></html>""") else: self.response.out.write("No existe un usuario con dicho nombre<br>") self.response.out.write("</body></body>")

Cuando se presiona el botón modificación del formulario anterior se ejecuta la clase Modificacion donde se procede a modificar el nombre y clave del usuario. Por último se redirige a la raiz del sitio:

class Modificacion(webapp.RequestHandler): def post(self): nomoculto=cgi.escape(self.request.get('nombreoculto')) nom=cgi.escape(self.request.get('nombre')) cla=cgi.escape(self.request.get('clave')) usuario=db.GqlQuery("select * from TablaUsuarios where nombre=:1",nomoculto) usu=usuario.fetch(1) if len(usu)>0: usu[0].nombre=nom usu[0].clave=cla usu[0].put() self.redirect("/")