Sie sind auf Seite 1von 72

PROGRAMACIN ORIENTADA A OBJETOS EN PYTHON

Python es uno de los lenguajes de programacin multiparadigma, ms potente y que menor curva de aprendizaje demanda. Con Python puedes crear tanto robustas aplicaciones de escritorio como Web, con muy pocas lneas de cdigo y en muy poco tiempo. En esta gua te propongo aprender Python programando a lo grande Te animas al desafo?

EL DESAFO
Comenzaremos programando con pocas introducciones. El objetivo, es que desde el comienzo, tomes tu editor de textos favoritos, te sientes a programar a la par de cada captulo, ejecutes tus cdigos y aprendas mientras programas. Al final de cada captulo, encontrars un chuleta con el resumen de lo que habrs aprendido. Y con tan solo 90 por captulo, en 15 horas estars en condiciones de programar, como un verdadero Pythonista.

QU NECESITAS? Un editor de textos


Pues desempolva tu legendario editor de textos, ese favorito que has tenido por siempre. No tienes un editor de textos favorito? Si tienes un S.O. GNU/ Linux chale un vistazo a esta lista de editores de texto para Linux. En cambio si utilizas Windows, puedes descargar Notepad++ para Windows

Instalar Python Si utilizas un SO GNU/Linux, seguramente ya tienes Python instalado. Para


comprobarlo, abre una terminal y simplemente escribe: python y pulsa enter. Nota: Si utilizas MacOS X, el procedimiento para comprobar si tienes Python instalado, es el mismo. Aparece un texto como este? Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) [GCC 4.4.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> Entonces Tienes Python instalado! No ves el texto anterior? Entonces escribe: sudo apt-get install python

Y Listo! Sigue las instrucciones en pantalla y tendrs Python instalado. En cambio, si utilizas Windows puedes lee el tutorial completo de instalacinInstalando Python en Windows de Ricardo Azpeitia en Foros del Web. Ahora s, ests listo? A programar!

CAPTULO I: PRIMEROS PASOS CON PYTHON


Hagamos algo til. Crearemos un mdulo Python mediante el cual, nos pida algunos datos y con ellos, nos imprima un presupuesto para enviarle nuestros clientes.

MDULO
Un mdulo es un archivo escrito en Python, con extensin .py
El resultado final tras ejecutar el mdulo que crearemos, ser similar al siguiente:

Este ser el resultado de nuestro primer mdulo hecho en Python

1. 2. 3. 4.

Abre el editor de textos Copia el cdigo que est ms abajo Guarda el archivo como presupuesto.py Abre una terminal/consola

5. Navega hasta el directorio donde haz guardado el archivo 6. Ahora escribe python presupuesto.py y ve como funciona. 7. Ahora escribe python presupuesto.py y ve como funciona.

TIP
Un mdulo python puede ejecutarse mediante una terminal escribiendo: python nombre_del_archivo.py CDIGO FUENTE QUE DEBES COPIAR Y PEGAR EN EL ARCHIVO PRESUPUESTO.PY
# -*- coding: utf-8 -*class ModeloDePresupuesto: # Datos comerciales titulo = "PRESUPUESTO" encabezado_nombre = "Eugenia Bahit" encabezado_web = "www.eugeniabahit.com.ar" encabezado_email = "mail@mail.com" # Datos impositivos alicuota_iva = 21 # Propiedades relativas al formato divline = "="*80 # Setear los datos del cliente def set_cliente(self): self.empresa = raw_input('\tEmpresa: ') self.cliente = raw_input('\tNombre del cliente: ') # Setear los datos bsicos del presupuesto def set_datos_basicos(self): self.fecha = raw_input('\tFecha: ') self.servicio = raw_input('\tDescripcin del servicio: ') importe = raw_input('\tImporte bruto: $') self.importe = float(importe) self.vencimiento = raw_input('\tFecha de caducidad: ') # Calcular IVA def calcular_iva(self): self.monto_iva = self.importe*self.alicuota_iva/100 # Calcula el monto total del presupuesto def calcular_neto(self): self.neto = self.importe+self.monto_iva # Armar el presupuesto def armar_presupuesto(self): """

Esta funcin se encarga de armar todo el presupuesto """ txt txt txt txt txt txt txt txt txt txt txt txt txt txt = '\n'+self.divline+'\n' += '\t'+self.encabezado_nombre+'\n' += '\tWeb Site: '+self.encabezado_web+' | ' += 'E-mail: '+self.encabezado_email+'\n' += self.divline+'\n' += '\t'+self.titulo+'\n' += self.divline+'\n\n' += '\tFecha: '+self.fecha+'\n' += '\tEmpresa: '+self.empresa+'\n' += '\tCliente: '+self.cliente+'\n' += self.divline+'\n\n' += '\tDetalle del servicio:\n' += '\t'+self.servicio+'\n\n' += '\tImporte: $%0.2f | IVA: $%0.2f\n' % ( self.importe, self.monto_iva) txt += '-'*80 txt += '\n\tMONTO TOTAL: $%0.2f\n' % (self.neto) txt += self.divline+'\n' print txt # Mtodo constructor def __init__(self): print self.divline print "\tGENERACIN DEL PRESUPUESTO" print self.divline self.set_cliente() self.set_datos_basicos() self.calcular_iva() self.calcular_neto() self.armar_presupuesto() # Instanciar clase presupuesto = ModeloDePresupuesto()

ENTENDIENDO EL CDIGO
Expliquemos el cdigo paso a paso:

ENCONDING DEFINIR CODIFICACIN DE CARACTERES


# -*- coding: utf-8 -*Python necesita que le indiquemos la codificacin de caracteres que utilizaremos. Entonces, lo indicaremos en la primera lnea del cdigo.

ENCODING
Debe ser la primera lnea del cdigo Sintaxis: # -*- coding: CODIFICACION -*-

CLASES EN PYTHON
class ModeloDePresupuesto: En la programacin, un objeto es una entidad provista de mtodos (funciones) y atributos. Haciendo un paralelismo con la realidad, podemos decir que: Una persona, realiza varias acciones (funciones) como caminar, saltar, correr, comer, dormir, etc. y tiene diferentes atributos como el color de pelo, su estatura, su peso, el color de sus ojos, etc. Pero, decir persona es muy abstracto, pues yo no soy persona, todos somos personas. Yo soy Eugenia, tu eres Jos o no te llamas Jos?, tu madre es Ana (a qu adivino nuevamente: tu madre no se llama Ana) y en definitiva, todos somosobjetos: Eugenia, Jos y Ana y como objetos somos una clase de persona. Entonces:

Una clase es un modelo para definir objetos que pueden realizar las mismas acciones y poseen caractersticas similares.
En nuestro caso, crearemos decenas, miles y millones (ojal!) de presupuestos.Cada uno de nuestros presupuestos, ser un objeto que

se crear en base al modelo ModeloDePresupuesto definido en la clase.

CLASES
Una clase se define mediante class NombreDeLaClase: COMENTANDO CDIGO EN PYTHON
Mira las lneas que comienzan con el signo # (como esta): # Datos comerciales Todas las lneas comenzadas por # son comentarios en el cdigo fuente. Y aquellos bloques de texto, encerrados entre tres comillas dobles como ste: """ Esta funcin se encarga de armar todo el presupuesto""" Tambin son comentarios, pero que adems, sirven para generar la documentacin de un mtodo.

COMENTARIOS
Para comentar y documentar cdigo en Python utiliza: # comentario o sino """ documentacin """ DEFINICIN DE VARIABLES EN PYTHON
# Datos comerciales titulo = "PRESUPUESTO"

encabezado_nombre = "Eugenia Bahit" encabezado_web = "www.eugeniabahit.com.ar" encabezado_email = "mail@mail.com" # Datos impositivos alicuota_iva = 21 Las variables, en nuestro ModeloDePresupuesto, son las propiedades (o atributos) caractersticos de nuestro presupuesto. Para definir una propiedad (atributo o variable) se utiliza: nombre_de_la_variable = dato

VARIABLES
Las variables en Python se definen mediante nombre_variable = dato
El nombre de una variable puede empezar (y continuar) por: Maysculas, minsculas, guiones bajos y tambin contener nmeros. Algunos ejemplos: variable _otra_variable_ variable_con_numero_25 VARIABLE_CON_MAYUSCULAS Variable_Mixta

TIPOS DE DATOS
Las variables pueden contener datos de diversos tipos, por ejemplo:

Cadenas de texto
nombre_de_la_variable = "Las cadenas de texto van entre comillas"

Nmeros enteros y nmeros flotantes


numero_entero = 100 numero_flotante = 1298.95

Datos booleanos (verdadero o falso)


variable_con_dato_verdadero = True variable_con_dato_falso = False

REPITIENDO CADENAS DE TEXTO


# Propiedades relativas al formato divline ="="*80 Utilizando el asterisco * seguido de un nmero, estamos indicando la cantidad de veces que repetiremos la cadena de texto colocada entre comillas: variable_1 = "a"*3 es igual que: variable_1 = "aaa" Si has llegado hasta ac sin problemas, eso quiere decir que has cumplido con el primer paso para aceptar el reto de aprender Python programando. No te pierdas el segundo captulo y recuerda que toda duda ser resuelta en los comentarios.

MTODOS Y PROPIEDADES EN PYTHON


En este segundo captulo, seguimos con nuestro ejemplo presupuesto.pyintroducindonos a desarrollar, los temas pendientes del captulo I, pero no sin antes, unos consejos para razonar errores de cdigo como un programador profesional: 1. No desesperes. La magia en la programacin no existe. Si el cdigo falla, es porque algo hemos hecho mal. 2. Lee detenidamente el error que Python devuelve (presta atencin a las ltimas lneas donde se detalla lnea en la que falla, mtodo o algoritmo donde se produce y descripcin del error). Un ejemplo: 3. Traceback (most recent call last): File "", line 1, in File "presupuesto.py", line 158, in presupuesto = ModeloDePresupuesto() File "presupuesto.py", line 152, in __init__ self.set_datos_basicos() File "presupuesto.py", line 45, in set_datos_basicos self.seleccionar_plan() File "presupuesto.py", line 59, in seleccionar_plan
elegir_plan = int(elegir_plan)

ValueError: invalid literal for int() with base 10: '' >>> 4. Intenta resolverlo tu mismo cmo? a. lee la descripcin del error y piensa como se produjo (es decir, cul fue el paso previo) b. verifica la lnea de cdigo donde se produjo el error sintaxis? c. Compara el cdigo con el del ejemplo. Lo ves igual? Entonces no pierdes nada, copindolo textualmente de nuevo. d. Sigue fallando? busca el error en Internet (Google?) 5. Si no logras resolverlo, busca ayuda: aqu, en foros o listas de correo, PERO, previamente ten en cuenta: a. Copia el error completo, tal cual se muestra y colcalo como referencia en tu post b. Copia tu cdigo en algn sitio que te permita compartir y corregir cdigo pblicamente, como por ejemplohttp:// pastebin.lugmen.org.ar/ c. Coloca en tu post, un enlace hacia el cdigo del Pastebin Pero por qu tanto lo si es ms sencillo preguntar y listo?. Creme: no lo es. Podr ser simple preguntar sin intentar resolverlo, pero ser complejo cuando comiences a leer las posibles soluciones, pues pueden no

estar basadas en la verdadera causa (nadie est all para conocer tu cdigo ni como se produjo el error). Y por otro lado, si no intentas resolverlo tu mismo, te ser ms difcil aprender. Ahora s, retomemos nuestro cdigo!

DEFINICIN DE FUNCIONES EN PYTHON


def set_cliente(self):

Una funcin (o mtodo) es la forma de definir una determinada accin que realiza un objeto.

DEFINIR FUNCIONES
Para definir una funcin, se escribe: def nombre_de_la_funcion(parmetros): # aqu escribimos el cdigo que realiza la accin que definimos Los parmetros son datos contenidos en variables (una o ms), que la funcin necesitar para realizar la accin. No siempre son necesarios. En nuestro caso, el parmetro self indica que la funcin requerir de los atributos contenidos en la clase (los que ya vimos recientemente). Por ejemplo: self.empresa est llamando al atributo empresa de la clase. Mientras que mediante: self.empresa = 'Maestros del Web', le estoyasignando el valor Maestros del Web al atributo empresa de la clase (recuerda que un atributo es una variable).

REFERENCIA A PROPIEDADES
Cuando necesito recurrir a un atributo de la clase, dentro de una funcin, escriboself.nombre_del_atributo Todo el cdigo contenido dentro de una funcin (es decir, el que est debajo de la definicin de la funcin, con tabulado), se llama algoritmo, y es el que indicar a la funcin, qu es lo que debe hacer.

INTERACTUANDO CON EL USUARIO MEDIANTE RAW_INPUT


def set_cliente(self): self.empresa = raw_input('\tEmpresa: ') self.cliente = raw_input('\tNombre del cliente: ')

raw_input() es una funcin. Pero no la definimos nosotros, sino que es una funcin nativa de Python. La accin que realiza raw_input('Texto que le mostrar al usuario'), es: 1. Muestra al usuario el texto que se encuentra entre comillas, dentro de los parntesis (es decir, que este texto es un parmetro requerido por la funcin) 2. Espera que el usuario escriba algo 3. Luego, almacena lo que el usuario escribi. En nuestro caso, ser almacenado en los atributos de la clase, empresa y cliente.

FLOAT() OTRA FUNCIN NATIVA (PROPIA) DE PYTHON


importe = raw_input('\tImporte bruto: $') self.importe = float(importe)

Hemos almacenado en la variable importe un dato ingresado por el usuario:


importe = raw_input('\tImporte bruto: $')

Luego, asignamos esa variable (importe) como valor del atributo importe, pero esta vez, es el atributo importe de la clase:
self.importe = float(importe)

FUNCIONES NATIVAS
Float() al igual que raw_input() es una funcin nativa de Python. Su accin consiste en convertir en nmero flotante (es decir, con decimales), el nmero que le sea pasado como parmetro.

OPERADORES MATEMTICOS: SUMAR, RESTAR, DIVIDIR Y MULTIPLICAR CON PYTHON


self.monto_iva = self.importe*self.alicuota_iva/100 self.neto = self.importe+self.monto_iva

Podemos realizar sumas, restas, multiplicaciones y divisiones con Python. Y podemos almacenar los resultados de nuestras operaciones matemticas en variables, incluso aquellas que sean atributos de la clase. Podemos realizar operaciones matemticas con nmeros: 1+1 y tambin con variables cuyos valores sean nmeros: variable_1+variable_2

OPERADORES MATEMTICOS
Para Para Para Para Para Para Para sumar, utilizamos + restar utilizamos dividir flotantes utilizamos / dividir enteros utilizamos // multiplicar utilizamos * obtener el resto de una divisin utilizamos % exponenciar utilizamos **

EL OPERADOR MATEMTICO SUMA (+)


txt = '\n'+self.divline+'\n' txt += '\t'+self.encabezado_nombre+'\n'

El operador matemtico + no solo sirve para sumar nmeros. Tambin sirve para concatenar cadenas de texto (es decir, unirlas). Fjate esta lnea:
txt = '\n'+self.divline+'\n'

Estoy diciendo que la variable txt es igual a: la cadena de texto \n (\n significa salto de lnea) ms el texto contenido en el atributo divline de la clase ms nuevamente, una cadena de texto \n Luego, mira la lnea que le sigue:
txt += '\t'+self.encabezado_nombre+'\n'

Estoy diciendo aqu, que a la variable txt de antes, le agregue ahora, todo lo dems: La cadena de texto \t (\t significa tabular) el texto contenido en el atributo encabezado_nombre de la clase ms finalmente, la cadena de salto de lnea \n

DANDO FORMATO A CADENAS DE TEXTO


txt += '\tImporte: $%0.2f | IVA: $%0.2f\n' % (self.importe, self.monto_iva)

Haz visto lo difcil de entender que parece este cdigo? Pues Pirdele el miedo! Es mucho ms sencillo de lo que parece. Python nos da la posibilidad de utilizar comodines en nuestras cadenas de texto, para poder reemplezar datos, que necesiten un formato especial. El comodn es el signo del porcentaje %. A este comodn, le segurir un patrn, que identifique el tipo de dato (formato) que queremos darle al dato. Por ejemplo: %0.2f, est indicando que en ese lugar (en vez del comodn

y el patrn), debe ir un nmero flotante con dos decimales. Es decir que el patrn 0.2fsignifica nmero con dos decimales. Hasta all, entonces, asignamos comodines y patrones. Pero luego, hay que decirle a Python qu datos debe formatear. Para ello, luego de la cadena de texto, escribimos un comodn % segudio de un espacio, y entre parantsis y separados por coma, las variables que contienen los datos a reemplazar. Vemoslo con otro ejemplo:
a = 10 b = 5 resultado = "%0.2f y %0.2f son dos nmeros flotantes" % (a, b)

Eso, sera como haber escrito esto:


resultado = "10.00 y 5.00 son dos nmeros flotantes"

IMPRIMIENDO TEXTO EN LA PANTALLA


print txt

Cuando quieres mostrar texto en la pantalla, solo debes escribir print y lo que desees mostrar. Pueden ser tanto los datos contenidos en una variable (como en nuestro cdigo) o directamente un dato, como en los siguientes ejemplos:
print 25 print "Cadena de texto"

CREACIN DE OBJETOS
# Instanciar clase presupuesto = ModeloDePresupuesto()

Recuerdas cuando hablamos de la diferencia entre clases y objetos? Decamos que una clase es un modelo que sirve como base para crear un objeto. Pues bien. Es hora de crear nuestro nuevo objeto: un nuevo presupuesto.

CREAR OBJETOS
Para instanciar una clase y crear un nuevo objeto se escribe: nombre_del_objeto = NombreDeLaClase() Con lo anterior, hemos iniciado un nuevo objeto que ser creado segn el modelo NombreDeLaClase.

MTODO CONSTRUCTOR DE LA CLASE: __INIT__


# Mtodo constructor

def __init__(self):

def __init__(self): es la definicin de una funcin, al igual que todas las anteriores lo notas? Pero el nombre de la funcin __init__, Python lo reserva para los mtodos constructores.

Un mtodo constructor de una clase, es una funcin que se ejecuta automticamente cuando crea un objeto.
Estos mtodos son sumamente tiles, cuando (como en nuestro caso), necesitamos automatizar todas las tareas. Anteriormente, vimos como crear el objeto. Si no hubisemos generado un mtodo __init__, lo que vimos al comienzo cuando ejecutamos presupuesto.py en la consola, no hubiese sido posible, ya que tendramos que haberle dicho manualmente a nuestro objeto, que realice cada una de las acciones, por ejemplo: presupuesto.set_cliente() para que realice la accin de crear los datos del cliente presupuesto.calcular_iva() para que calculara el importe de IVA Y as con cada accin definida en la clase. Pero, el mtodo __init__ nos facilita la vida. Pues all dentro, os encargamos de llamar a todas las funciones (acciones) en el orden correcto, ahorrndonos mucho tiempo:
def __init__(self): # en las siguientes lneas, imprimo texto en pantalla print self.divline print "\tGENERACIN DEL PRESUPUESTO" print self.divline self.set_cliente() # aqu seteo los datos del cliente self.set_datos_basicos() # aqu los del presupuesto self.calcular_iva() # calculo el iva self.calcular_neto() # calculo el importe total self.armar_presupuesto()

Finalmente, llam a la funcin que se encarga de convertir a texto todo el presupuesto.

LLAMAR FUNCIN DENTRO DE OTRA


Para llamar a una funcin y que sta, se ejecute en el interior de otra, se utilizaself.nombre_de_la_funcion()

CHULETA DE LOS CAPTULOS I Y II

NUEVO DESAFO

En el captulo de hoy, nos extendimos en cuestiones tericas sobre referencias del lenguaje que utilizamos en nuestro primer ejemplo. Aprendimos muchas cosas nuevas como: Definir funciones Utilizar funciones nativas de Python Operadores matemticos Dar formato a cadenas de texto Entre otras Pero algo muy importante que aprendimos es a perderle el miedo a los errores de cdigo y tratar de resolverlos. Y si quieres convertirte en verdadero profesional, te invito a sumarte a un nuevo desafo. A continuacin, encontrars un cdigo fuente. Este cdigo, utiliza algunas cosas que ya hemos aprendido. Adems, no te dir donde, pero tiene algn que otro error. EL RETO DE HOY 1. Copia el siguiente cdigo en un archivo, con el nombre que se te ocurra 2. Ejectalo en una terminal (ya sabes como) 3. Ve si puedes encontrar el (o los) error(es) y corregirlo(s) 4. Si encuentras el(los) error(es), NO lo postees as das tiempo a los dems a hacer lo mismo. Pero, puedes contar que los encontraste y dar pistas para ayudar a otros. 5. Si NO encuentras los errores, puedes postear preguntando a quienes s los hayan encontrado

Si aprendes a trabajar en equipo, colaborando con tus pares (ya sea ofreciendo o pidiendo ayuda) y evitando la competencia, estars listo para afrontar verdaderos desafos laborales, que harn que tu carrera se destaque.
AQU, EL CDIGO FUENTE
# -*- coding: utf-8 -*class Modelo: def __init__(self): self.divisor = 23 valor = raw_input("Elige un nmero entero entre 0 y 100: "); resultado = self.devolver_resultado(valor) print "%d/%d es %d" % (valor, self.divisor, resulatdo) def devolver_resultado(self, numero): """Divide el nemro por el divisor y devuelve un entero""" resultado = numero//self.divisor return resultado

obj = Modelo()

RECUERDA: Si encuentras el error (o los errores), no lo postees hasta que al menos 5 personas hayan indicado que pudieron corregirlo.

LISTAS, TUPLAS, DICCIONARIOS Y ESTRUCTURAS DE CONTROL


Muy buenas Pythoneros! estamos aqu con la tercera entrega de Aprender Python Programando. El desafo de hoy, no es apto para personas impresionables, pues Bienvenid@s a un nuevo reto para corajud@s! Qu haremos? Hoy agregaremos ms funcionalidad a nuestro mdulo Presupuesto. 1. Disearemos una plantilla HTML y otra plantilla TXT para

nuestro presupuesto, as, no solo se ver ms agradable, sino que adems, ser ms fcil modificarlo 2. Comenzaremos a colocar una numeracin incremental automtica, a cada nuevo presupuesto que generemos 3. Podremos elegir entre guardar el archivo en formato HTML o mostrarlo en pantalla 4. Crearemos una lista de precios Basta de agregar tantos datos manualmente!
Finalmente, nuestro programa se ver as:

Produciendo presupuestos en formato HTML, como el siguiente:

CMO FUNCIONAR AHORA?


Ahora, solo nos pedir: 1. Los datos de la empresa y la fecha del presupuesto (igual que 2.

3. 4. 5. 6. 7.

antes) En vez de detallar el servicio y el importe, los obtendr de una lista de precios, por lo cual, solo nos pedir ingresar el cdigo correspondiente al plan: 0: Plan corporativo 1: Plan personal 2: Plan de mantenimiento Calcular automticamente el nmero de presupuesto, y Finalmente nos preguntar si deseamos guardar el archivo: a. Si elegimos S (si), guardar un HTML y nos informar el nombre del archivo (que ser el nmero de presupuesto con extensin .html) b. Si elegimos N (no), nos mostrar el presupuesto en pantalla como lo haca hasta ahora c. Si nos equivocamos, y no elegimos ni S (si) ni N (no), nos avisar que ingresamos una opcin incorrecta, y nos dar la oportunidad, de volver a elegir.

Comencemos!

ARCHIVOS NECESARIOS
Para hacerte de los archivos necesarios, sigue los temes de esta lista, paso por paso: 1. Crea una carpeta llamada capitulo3 2. Aqu almacenaremos todos los archivos del programa 3. Dentro de la carpeta capitulo3, crea una subcarpeta

llamadapresupuestos 4. Aqu se guardarn todos los presupuestos generamos en formato HTML (los que decidamos guardar) 5. Dentro de la carpeta capitulo3, crea otra subcarpeta llamada templates 6. Aqu guardaremos la plantilla HTML y otra con formato solo texto (TXT) 7. Dentro de la carpeta templates guarda los archivos template.html ytemplate.txt 8. Pulsa en cada archivo para descargarlos desde Launchpad. Estas sern, nuestras dos plantillas 9. Dentro de la carpeta capitulo3, crea un archivo llamado contador.txt 10. Ser la gua que utilizaremos para calcular incrementalmente nuestros nmeros de presupuesto. 11. Abre el archivo contador.txt, edita el contenido (est vaco), escribe 100 y guarda los cambios 12. Inicializamos el contador en 100. Nuestro primer presupuesto, obtendr el nmero 101 y as sucesivamente de forma incremental. 13. Dentro de la carpeta capitulo3, guarda el mdulo presupuesto.py(modificado) 14. Explicaremos todos los cambios nuestro mdulo, a lo largo del captulo. Finalmente, la estructura de archivos y directorios, deber verse as:
[-]capitulo3 |_ [+]presupuestos |_ [-]templates |_ template.html |_ template.txt |_ contador.txt |_ presupuesto.py

LA LISTA DE PRECIOS: LISTAS, TUPLAS Y DICCIONARIOS


Te voy a pedir que abras el mdulo Presupuesto (presupuesto.py) y vayas a lalnea 22: # Planes y servicios - Captulo 3

planes = ('corporativo', 'personal', 'mantenimiento') Tupla corporativo = ['Diseo Sitio Web corporativo', 7200] Lista personal = ['Diseo Sitio Web bsico', 4500] Lista mantenimiento = ['Mantenimiento sitio Web (mensual)', 500] Lista lista_precios = {'corporativo':corporativo, 'personal':personal, 'mantenimiento':mantenimiento} Diccionario

# # # #

Como vers, hemos agregado cuatro nuevas propiedades de clase a nuestro mdulo. Pero, el tipo de datos, no es ninguno de los que ya hemos visto! Pertenecen a tres nuevos tipos de datos: tuplas, listas y diccionarios. Tanto las tuplas, como listas y diccionarios, son una forma de almacenar varios datos diferentes, de diversos tipos (cadenas de texto, enteros, flotantes, booleanos) en una misma variable. El orden en el cual estos datos se especifican dentro de la variable, se denomina ndice, teniendo el primer dato un ndice 0 (cero), el siguiente 1, y as incrementalmente. Veamos estos tres nuevos tipos de datos en detalle:

TUPLAS
planes = ('corporativo', 'personal', 'mantenimiento') El contenido de una tupla se escribe siempre entre parntesis ( ) Admite cualquier tipo de dato: mi_tupla = (texto, 100, 7.25, False, True) Para acceder a uno de esos datos, se realiza por su nmero de ndice:

texto es ndice 0; 100 es ndice 1; 7.25 es ndice 2; False es ndice 3 y,True es ndice 4
Para acceder a una variable por su nmero de ndice, ste se escribe

entre corchetes: print mi_tupla[2] imprimir 7.25 mientras que print mi_tupla[4] imprimir True
Los datos contenidos en una tupla no pueden modificarse. En nuestro cdigo, la tupla planes lo que est haciendo es almacenar el nombre de los tres tipos de planes que ofreceremos a nuestros clientes.

LISTAS
corporativo = ['Diseo Sitio Web corporativo', 7200]

personal = ['Diseo Sitio Web bsico', 4500] mantenimiento = ['Mantenimiento sitio Web (mensual)', 500]

El contenido de una lista se escribe siempre entre corchetes [ ] Admite cualquier tipo de dato: mi_lista = ['texto', 100, 7.25, False, True] Para acceder a uno de esos datos, se realiza por su nmero de ndice al igual que con las tuplas: print mi_lista[2] imprimir 7.25 mientras que print mi_lista[4] imprimir True

A diferencia de las tuplas, los datos contenidos en una lista

PUEDEN modificarse, accediendo a ellos por su nmero de ndice: mi_lista[0] = 'otro contenido'
En nuestro cdigo, hemos creado una lista para cada tipo de plan, donde el ndice 0 (cero) ser la descripcin del servicio y el ndice 1, el precio de ese servicio.

DICCIONARIOS
lista_precios = {'corporativo':corporativo, 'personal':personal, 'mantenimiento':mantenimiento} El contenido de un diccionario se escribe siempre entre llaves { } Admite cualquier tipo de dato Cada dato almacenado en un diccionario, debe llevar un nombre de

claveantecediendo al dato: diccionario = {'nombre_de_clave':'texto', 'numero_entero':100, 'numero_flotante':7.25, 'falso':False, 'verdadero':True}


Para acceder a uno de esos datos, se realiza por su nombre de

clave: print diccionario['numero_entero'] imprimir 100 y si deseo modificar 100 por 125, escribo: diccionario['numero_entero'] = 125. Es decir que al igual que las listas, se pueden modificar los datos.
En nuestro cdigo, hemos creado un diccionario para englobar el nombre de nuestros planes (que actuar como nombre de clave) y el valor de cada clave, ser cada una de nuestras listas.

PARA SABER
Las tuplas, listas y diccionarios, admiten tambin como valores, otras tuplas, listas y/o diccionarios!
tupla1 = ('rosa', 'verde', 'rojo') tupla2 = (tupla1, 'celeste') tupla3 = ('hortensia', 'neomarica', 'rosa', 'jazmin') lista1 = [tupla1, tupla2, 'negro', 'amarillo'] lista2 = [lista1, 'naranja'] diccionario1 = {'colores':lista2, 'plantas':tupla3} gran_tupla = (diccionario1, 'y algo ms!')

Hasta aqu vemos como acceder uno a uno a los datos de una tupla, lista o diccionario. Pero qu sucede si queremos recorrerlos todos y no sabemos cuantos ndices tiene? Para ello, utilizaremos una estructura de control llamada bucle for.

Una estructura de control es un bloque de cdigo que permite tomar decisiones de manera dinmica, sobre cdigo existente.
EL BUCLE FOR
En nuestro cdigo, la estructura de control que estamos implementado se denomina bucle for y es la que se encuentra representada por el siguiente bloque de cdigo (lneas 44, 45 y 46): for plan in self.planes: texto_a_mostrar += '(%d)%s ' % (codigo_plan, plan) codigo_plan = codigo_plan+1

Por qu bucle? Porque es una accin que no se ejecuta solo una vez, sino que lo har hasta que una condicin deje de cumplirse. Qu condicin? la que restringe la ejecucin de ese bucle. En nuestro caso, la condicin estar delimitada por la cantidad de planes en nuestra tupla planes: for plan in self.planes:
Lo anterior puede leerse as:

[for] por [plan] cada plan [in] en self.planes [:] hacer lo que sigue Es decir que el condicionamiento (limitacin) est dado por la cantidad de planes contenidos en la propiedad de clase, planes. Luego, en cada iteracin (es decir, cada repeticin dentro del bucle) voy

agregando texto a la variable texto_a_mostrar utilizando una cadena con comodines los recuerdas? Utilizo el patrn d que indica que all ir un dgito y el patrn s indicando que lo reemplazar por una string, tal cual lo vimos en captulos anteriores: texto_a_mostrar += '(%d)%s ' % (codigo_plan, plan) Ese texto_a_mostrar es el que se utiliza luego en el raw_input() para preguntar qu tipo de plan ofrecer. Pero el cdigo de plan lo genero dinmicamente Cmo? Antes del bucle for, inicializo la variable codigo_plan en cero:

codigo_plan = 0
En el bucle for, la voy incrementando en 1, con cada iteracin:

codigo_plan = codigo_plan+1 Qu obtengo? El ndice de cada plan dentro de la tupla:


ndice 0: corporativo ndice 1: personal ndice 2: mantenimiento Y de dnde surge la variable plan? se declara automticamente en el bucle for:

for plan in self.planes: CONVIRTIENDO A ENTEROS CON INT()


Siguiendo con el mtodo anterior, destinado a la seleccin de planes, pido ingresar el cdigo correspondiente al plan, que a la vez ser el nmero de ndice del plan, dentro de la tupla planes: elegir_plan = raw_input(texto_a_mostrar) raw_input() retorna el valor ingresado, como cadena de texto. Pero necesito utilizarlo como nmero de ndice! entonces, convierto ese valor a entero, con otra funcin nativa de Python: int() elegir_plan = int(elegir_plan)

ACCEDIENDO A DATOS POR SU NMERO DE NDICE


Cuando ingresamos el cdigo de plan (0, 1 2) estamos ingresando un nmero de ndice. Mediante: self.plan = self.planes[elegir_plan] Lo que estoy haciendo, es traer el nombre (valor) del tipo de plan almacenado en la tupla planes. Los datos del servicio a cotizar como descripcin y precio, los he guardado en el diccionario lista_precios. Recordemos que al diccionario se accede por nombre de clave. ste, lo obtuve antes haciendo self.planes[elegir_plan]. Entonces, accedo al diccionario para traerme la lista, que contiene descripcin del servicio e importe, utilizando como clave, el nombre del plan: datos_servicio = self.lista_precios[self.planes[elegir_plan]] Almaceno la lista correspondiente al plan en una ueva variable llamadadatos_Servicios.Pero esta variable, es una lista. Entonces, para obtener el servicio, debo recurrir al ndice 0: self.servicio = datos_servicio[0] Y para obtener el importe, al ndice 1:

importe = datos_servicio[1] Finalmente, formateo el importe con float(): self.importe = float(importe)

CHULETA #1
Con nuestra lista de precios hemos aprendido sobre: Tuplas mi_tupla = ('texto', 100, 25.83, False) Crear
Acceder Modificar

print mi_tupla[1] # Imprime: 100 No se puede! mi_lista = ['texto', 100, 25.83, False] print mi_lista[2] # Imprime: 25.83 mi_lista[0] = 'Otro valor'

Listas
Crear Acceder Modificar

Diccionarios: dict = {'clave':'dato', 'otra_clave':155} Crear


Acceder Modificar

print dict['otra_clave'] # Imprime: 155 dict['clave'] = 'Texto'

Recorrer listas, tuplas y diccionarios con bucle for flores = ['rosa', 'jazmn', 'crisantemo'] for flor in flores: print 'Flor de ' + flor Imprimir: Flor de rosa Flor de jazmn Flor de crisantemo Convertir un literal a entero: literal = '234' int(literal)
En el siguiente captulo veremos como logramos utilizar plantillas HTML para nuestros presupuesto y como fue el proceso para almacenarlos. Ahora, un desafo extra...

NUEVO RETO
Mirando el mtodo que se encuentra en la lnea 72 de nuestro mdulo Presupuesto: # Armar numero de presupuesto def armar_numero_presupuesto(self): contador = open('contador.txt', 'r+') # Abro contador

ultimo_num = int(contador.read()) numero nuevo = ultimo_num+1 nmero contador.seek(0) byte 0 nuevo = str(nuevo) a string contador.write(nuevo) nmero contador.close() self.numero_presupuesto = nuevo nmero

# obtengo ultimo # genero nuevo # muevo cursor a # convierto numero # sobreescribo el # cierro contador # seteo el nuevo

Leyendo los comentarios a la derecha de cada lnea Alguien se anima

a explicar por qu luego de abrir un archivo, leerlo y antes de escribirlo se utilizacontador.seek(0) para "mover el cursor al byte 0"?
Vamos a ver esto de forma detallada en el siguiente captulo, pero quin se anima a tratar de deducirlo y explircarlo?

TRABAJANDO CON TEMPLATES, ARCHIVOS Y CONDICIONALES


En el captulo anterior, estuvimos modificando nuestro programa: creamos una lista de precios y agregamos plantillas HTML y TXT para imprimir los presupuestos. Vimos como utilizar tuplas, listas y diccionarios e incorporamos una nuevaestructura de control mediante el bucle for en el proceso de creacin y utilizacin de listas de precios para nuestro programa.

En el captulo de hoy, veremos cmo logramos utilizar plantillas para generar nuestros presupuestos y el proceso para guardarlos.
Comenzaremos con algo sencillo y sumamente prctico: lectura y escritura de archivos.

LECTURA Y ESCRITURA DE ARCHIVOS


Al trabajar con archivos, existen cuatro acciones bsicas que podemos hacer con un archivo: Abrir un archivo Leer un archivo Escribir/sobrescribir un archivo Cerrar un archivo abierto Cuando abrimos un archivo podemos hacerlo con diversos fines:

Abrirlo para leerlo Abrirlo para escribirlo Abrirlo para leerlo y escribirlo, etc Para abrir un archivo se realiza mediante la clase open() de Python, cuyo mtodo constructor recibir como primer parmetro, la ruta del archivo a ser abierto y como segundo parmetro, el modo de apertura (es decir, el objetivo para el cual lo abrimos: escritura, solo lectura, lectura y escritura, etc.). En la lnea 103 abrimos un archivo para leerlo: filename = open(archivo, 'r') Donde archivo es la ruta del archivo pasada como parmetro en el mtodo leer_plantilla() y la cadena r representa el modo de apertura solo lectura. Mientras tanto, en la lnea 74, abrimos un archivo no solo para leerlo, sino tambin para escribirlo: contador = open('contador.txt', 'r+') En este caso, r+ significa lectura y escritura. Sin embargo, en la lnea 92, estamos abriendo un archivo, pero para crearlo. Utilizando en este caso el modo w, que crear el archivo si no existe (o lo reemplazar si existe, creando uno nuevo con el mismo nombre), preparndolo para ser escrito: presupuesto = open(filename, 'w') Tanto con la variable filename como con la variable contador y presupuesto, lo que estamos haciendo es crear un objeto archivo, para luego utilizar los mtodos necesarios: objeto.read() para leer el contenido de un archivo; objeto.write('nuevo contenido') para escribir en el archivo; objeto.seek(numero_de_byte) para mover el cursor hacia el byte indicado en el archivo; y objeto.close() para cerrar el archivo. Cuando leemos el contenido de un archivo con el mtodo read(), ste, retorna una cadena de texto. Si el contenido del archivo que estamos leyendo, es un nmero (como en nuestro contador.txt), obtendremos el literal de ese nmero y para poder utilizarlo como nmero (por ejemplo, para hacer operaciones matemticas), ser necesario convertirlo a entero o flotante, como en la lnea 75, donde medianteint() convertimos el literal ledo a nmero entero: ultimo_num = int(contador.read())

APRENDIENDO A UTILIZAR TEMPLATES EN PYTHON


IMPORTACIN DE MDULOS presupuesto.py es nuestro mdulo. Cualquier otro archivo con extensin .py, tambin es un mdulo. Python, tiene sus propios mdulos. Cualquier mdulo Python (propio o provisto por Python) puede ser importado.

IMPORTAR MDULOS
Importar un mdulo significa incluir un archivo .py dentro de otro, para utilizar sus mtodos. Para importar todo un mdulo, se escribe: import modulo Para importar solo una clase de un mdulo, se escribe: from modulo import Clase Para importar varias clases de un mdulo, se separan los nombres de las clases con comas: form modulo import ClaseUno, ClaseDos, ClaseVeinte
En nuestro ejemplo: form string import Template estamos importando la clase Template del mdulo string de Python. Esta clase, es la que nos va a permitir utilizar una plantilla para nuestro presupuesto y luego hacer un render (reemplazo dinmico) de datos.

XKCD This work is licensed under a Creative Commons Attribution-NonCommercial 2.5 license.

LA CLASE TEMPLATE DEL MDULO STRING DE PYTHON Mira la lneaa 131 y 132 del mdulo presupuesto.py:

txt = Template(txt).safe_substitute(diccionario) html = Template(html).safe_substitute(diccionario) Template() es una clase del mdulo string de Python. El constructor de esta clase (es decir, el mtodo __init__) recibe como

parmetro una plantilla: Template(txt) y Template(html)


Esta plantilla, debe tener ciertos comodines que indicarn los datos

que deben ser reemplazados.


Estos comodines se denominan identificadores. Los identificadores, se escriben con un signo $

delante:$nombre_del_identificador. Estos identificadores los hemos colocado en nuestro archivo template.txt y tambin en template.html
Para escribir un signo $ sin hacer referencia a un identificador,

debe escaparse con otro signo $. Esto: $$ imprime $, mientras que$nombre_identificador ser reemplazado por un identificador cuyo nombre sea nombre_identificador

Los mtodos substitute() y safe_substitute() de la clase Template Como nuestra clase Presupuesto, Template, tiene sus propios mtodos:substitute() y safe_substitute()
Ambos mtodos, reciben como parmetros, un diccionario de datos. Este diccionario se compone de clave=valor donde clave, ser

el nombre de un identificador y valor, el dato por el cul ser reemplazada la clave.


UN EJEMPLO SIMPLE from string import Template print Template('Reemplazar $identificador').substitute(identificador='valor de reemplazo') La salida de lo anterior, ser:

Reemplazar valor de reemplazo

MTODOS DE LA CLASE TEMPLATE


La diferencia entre el mtodo substitute() y safe_substitute(), es que

si nos olvidamos de colocar el valor para un identificador, el primer mtodo generar un error, mientras que el segundo, simplemente lo dejar sin reemplazar.
Es decir que si escribimos Template('Este es el $id1 y este $id2).safe_substitute(id1='Identificador Uno') La salida ser:

Este es el Identificador Uno y este $id2


Mientras que substitute provocara un error.

DICT(): CREACIN DE DICCIONARIO DE DATOS


Ve a al lnea 116 del mdulo presupuesto: diccionario = dict(nombre=self.encabezado_nombre, web=self.encabezado_web, email=self.encabezado_email, titulo=self.titulo, numero=self.numero_presupuesto, fecha=self.fecha, empresa=self.empresa, cliente=self.cliente, plan=self.plan, servicio=self.servicio, precio=self.importe, iva=self.monto_iva, total=self.neto, limite=self.vencimiento) Aqu lo que hicimos, fue armar un diccionario de datos con la clase dict() de Python. Podramos haber colocado estos pares de clave=valor dentro del mtodosafe_substitute() directamente. Pero para hacerlo ms legible y prolijo, creamos este diccionario de datos, que luego lo pasamos como parmetro a safe_substitute(): txt = Template(txt).safe_substitute(diccionario) html = Template(html).safe_substitute(diccionario)

CHULETA PARA UTILIZAR TEMPLATES


Para utilizar una plantilla, debemos: 1. Crear la plantilla en un archivo, colocando identificadores

antecedidos por el signo $ en los lugares donde necesitemos reemplazar los datos dinmicamente. 2. Importar la clase Template del mdulo string de Python: 3. from string import Template 4. Guardar el contenido de la plantilla en una variable: 5. # Crear un objeto archivo: Abrir el archivo en modo de solo lectura

archivo = open('archivo', 'r') # Leer el archivo contenido = archivo.read() # No olvidarse de cerrar el archivo archivo.close()

6. Crear un diccionario de datos con dict(): 7. diccionario = dict(id='un valor', otro_id='Otro valor') 8. Hacer un render de datos con la clase Template y el mtodo

substitute()o safe_substitute() (este ltimo, es mejor para prevenir errores): 9. Template(plantilla).safe_substitute(diccionario) 10. Dnde plantilla debe ser el contenido del archivo ledo previamente ydiccionario el creado mediante la clase dict()

CHULETA DE OPERACIONES BSICAS CON ARCHIVOS

ESTRUCTURAS DE CONTROL EN PYTHO: IF ELIF Y ELSE


Guardamos el presupuesto, lo imprimimos en pantalla, o? En el captulo anterior estuvimos hablando sobre estructuras de control con el bucle for. Hoy, incorporamos una nueva estructura de control: el condicional if:
if respuesta.lower() == 'n': print txt # si en cambio el usuario indica "n" elif respuesta.lower() == 's': filename = 'presupuestos/'+self.numero_presupuesto+'.html' presupuesto = open(filename, 'w') # Creo el archivo presupuesto.write(html) # escribo el contenido presupuesto.close() # cierro el archivo print '\n\tEl archivo se ha guardado en '+filename+'\n\n' # sino else:

print '\n\tOpcin incorrecta. No se guard el presupuesto.\n\n' self.guardar_presupuesto(txt, html) (ver lneas 87 a 99) El condicional if, elif y else, es uno de los que ms utilizars en tu vida como programador. Bsicamente, al igual que otras estructuras de control, permite tomar decisiones si una determinada condicin se cumple. El razonamiento de condicionales puede representarse como sigue: si condicion X se cumple: hacer esto sino, si condicion Y se cumple: hacer esto otro sino (si no se cumple ni X ni Y): hacer tal otra cosa No necesariamente el condicional debe cumplir esa estructura. A veces solo es necesario evaluar una nica condicin y tomar una decisin SOLO sobre la base de si esta condicin se cumple: si condicin X se cumple: hacer esto # fin Ejemplo: a = 10 if a == 10: print 'a es igual a 10' O tambin, tomar una decisin si la condicin se cumple y otra si no se cumple: a = 10 if a == 10: print 'a es igual a 10' else: print 'a no es igual a 10' Con elif se pueden tomar tantas decisiones como condiciones quieran evaluarse:: a = 10 if a == 10: print 'a es igual a 10' elif a == 9: print 'a es igual a 9' elif a == 75: print 'a no es ni 9 ni 10, es 75' Y si a lo anterior le agregamos else estaramos cubriendo todas las posibilidades: a = 10 if a == 10: print 'a es igual a 10' elif a == 9: print 'a es igual a 9' elif a == 75: print 'a no es ni 9 ni 10, es 75'

else: print 'a no es ni 9, ni 10 ni 75. Es un valor que no evalu' Retomemos nuestro cdigo. En el mtodo guardar_presupuesto() (lnea 84), lo primero que hago es preguntar si se desea guardar o no el presupuesto, siendo las respuestas esperadas s (s, lo deseo guardar) o n (no, no deseo guardarlo): respuesta = raw_input('\n\tDesea guardar el presupuesto? (s/n): ') Solo espero una de esas dos respuestas. Es necesario evaluar la respuesta ingresada. if respuesta.lower() == 'n': El mtodo lower() me convierte el valor ingresado por el usuario a minsculas, para que me sea ms sencillo evaluar la condicin. Bsicamente la condicin que estoy evaluando es: si la respuesta fue no. Al evaluar una condicin, la estructura de control responder con True (verdadero) o False (falso). Si la respuesta ingresada fue n, entonces la condicin cumple. Sino, si la respuesta fue s elif respuesta.lower() == 's': se est cumpliendo esta condicin (se eligi si). Pero tambin puede suceder, que ni s ni n sean ingresados. sto, lo evalo genericamente con else:

Razonando la estructura completa:


Si la respuesta es n, imprimo el presupuesto en pantalla if respuesta.lower() == 'n': print txt En cambio, si la respuesta es s, creo un nuevo archivo y lo guardo. elif respuesta.lower() == 's': filename = 'presupuestos/'+self.numero_presupuesto+'.html' presupuesto = open(filename, 'w') presupuesto.write(html) presupuesto.close() print '\n\tEl archivo se ha guardado en '+filename+'\n\n' Pero si la respuesta no es ni n ni s, vuelvo a ejecutar este mismo mtodo desde el comienzo, es decir que el mtodo guardar_presupuesto() se llama a s mismo: print '\n\tOpcin incorrecta. No se guard el presupuesto.\n\n' self.guardar_presupuesto(txt, html)

RECURSIVIDAD
Cuando un mtodo se llama a s mismo, se denomina recursividad. sto, genera una iteracin (un bucle) del mtodo en s mismo. Por lo tanto, se debe ser muy cuidadoso al emplear una llamada recursiva y hacerlo solo cuando sea estrictamente necesario y no se corra el riesgo de caer en un bucle infinito.

OPERADORES LGICOS Y RELACIONALES


Para evaluar condiciones no solo podemos recurrir a si X es igual a Y. Existen otros operadores que nos permitirn evaluar diferentes condiciones. Estos operadores se denominan operadores lgicos que nos permitirn evaluar mltiples condiciones en un mismo proceso y operadores relacionales, que nos permitirn evaluar la relacin existente en una condicin dada.

OPERADORES RELACIONALES
== != < > >= Igual que Distinto que Menor que Mayor que Mayor o igual que <= Menor o igual que

Usos: if a == b # si a es igual que b if a != b # si a es distinto que b if a > b # si a es mayor que b if a >= b # si a es mayor o igual que b if a < b # si a es menor que b if a <= b # si a es menor o igual que b OPERADORES LGICOS
and (y) or (o) not (no) Los operadores lgicos permitirn evaluar mltiples condiciones en una misma instancia: si condicion_1 and condicion_2 or condicion_3 and evala si todas las condiciones se cumplen, es decir, que todas las condiciones deben retornar True (verdadero) a = 10 b = 5 if (a == 10) and (b != 10): print 'Hola Mundo' Se lee: Si (a es igual que 10) y (b es distinto que 10) Como ambas condiciones se cumplen se imprimir Hola Mundo. Pero en el siguiente cdigo: a = 10 b = 5 if (a != 10) and (b == 5): print 'Hola Mundo' La primera condicin NO se cumple, entonces no se imprimir nada. or evala si alguna de las condiciones se cumple. Con que una sola condicin se

cumpla, se ejecutar la accin. a = 10 b = 5 if (a != 10) or (b == 5): print 'Hola Mundo' Se lee: si (a es distinto que 10) o (b es igual a 5). La primera condicin, no se cumple. Pero la segunda s se cumple. Entonces, imprimir Hola Mundo. not evala si la condicin NO se cumple: a = 10 b = 5 if not a == 10: print 'Hola Mundo' Se lee: si NO ES a igual que 10 (similar a escribir if a != 10) Como la condicin NO se cumple, no se imprimir nada.

MTODOS DEL OBJETO STRING


Vimos anteriormente que para evaluar la respuesta dada al preguntar si se desea guardar o no el presupuesto en un archivo, utilizamos el mtodo lower(). Este mtodo pertenece a la clase string de Python, y su funcin es la de convertir una cadena de texto en minsculas. La clase string de Python, adems del mtodo lower() tiene muchos otros mtodos que frecuentemente podrs utilizar. Para hacerlo, simplemente debes utilizar la sintaxis: tu_cadena.metodo() Otros mtodos de uso frecuente del objeto string son:

capitalize() Convierte el primer carcter de una cadena en mayscula upper() Convierte toda la cadena a maysculas lower() Convierte toda la cadena a minsculas swapcase() Convierte minsculas a maysculas y maysculas a minsculas Ms mtodos del objeto string, puedes verlos en este enlace.

NUEVO RETO: CONDICIONALES HASTA EN LA SOPA!


Dado el siguiente cdigo: # edades Ana = 43 Juan = 43 Pedro = 8 Roberto = 12 Melisa = 15 Helena = 3

if (Ana == Juan) and ((Helena < Melisa) or (Melisa < Roberto)) and not (Pedro > Roberto): print 'Veo condicionales hasta en la sopa!' else: print 'Soar con condicionales' El resultado, imprimir la frase Veo condicionales hasta en la sopa!.

EL DESAFO Modificando nicamente un operador lgico, debes lograr que se imprima


la frase Soar con condicionales. No se puede quitar ningn operador. Solo puede cambiarse un operador lgico por otro.

EXCEPCIONES, HELPERS Y REFACTORING


Bienvenid@s a la quinta entrega de Aprender Python Programando! En el captulo de hoy, nos vamos a poner ms tcnicos como verdaderos programadores. Mejoraremos no solo la funcionalidad externa de nuestro programa, sino que adems, emplearemos tcnicas de refactoring(refactorizacin) que nos ayuden a mejorar el rendimiento interno del programa.

QU HAREMOS HOY? 1. Agregaremos nuevas funcionalidades al programa y mejoraremos otras existentes: Haremos que tanto la fecha actual como la de caducidad de nuestro presupuesto, se calculen de forma automtica. Al finalizar la carga de un presupuesto, tendremos la opcin de abrirlo directamente en el navegador para visualizarlo. Mejoraremos el funcionamiento de la eleccin del plan a presupuestar, validando que el dato ingresado sea correcto. De no serlo, se nos volver a pedir que ingresemos una opcin. 2. Haremos un refactoring del cdigo, a fin de: Hacer nuestro cdigo ms legible. Lograr que el programa tenga un mejor rendimiento. Facilitar el mantenimiento y evolucin del sistema.

INGREDIENTES
Nuestra receta del captulo hoy, necesitar nuevos archivos e incorporar modificaciones. Lo primero que haremos es:

Descargar archivos modificados: presupuesto.py Descargar los archivos nuevos:


Si lo deseas, puedes modificar el nombre de la carpeta capitulo3 por el nombre que desees otorgarle al programa, o dejarlo sin cambios y guardar los siguientes archivos, dentro de ella.

constantes.py helpers.py

HELPERS: UNA FORMA DE AGRUPAR FUNCIONES GENRICAS


Hemos creado un nuevo archivo: helpers.py. En este archivo, hemos agrupadofunciones de uso comn, que si bien hoy, son utilizadas por nuestro mdulo Presupuesto, al ser funciones genricas (no son acciones propias del objeto presupuesto, sino que aplicaran a cualquier otro objeto), el da de maana, podramos utilizarlas en otros mdulos de nuestro sistema.

HELPER
En la programacin, un helper es una forma de agrupar funciones de uso comn, destinadas a servir de ayuda a otros procesos. Un Helper se compone de funciones genricas que se encargan de realizaracciones complementarias, aplicables a cualquier elemento de un sistema.
Es importante mencionar, que un Helper, pueden ser, tanto funciones sueltas como la abstraccin de un objeto helper (es decir, una clase). class Helper: def helper_1(self): # algoritmo def helper_2(self): # algoritmo Es tan (o ms) vlido que: def helper_1(self): # algoritmo def helper_2(self): # algoritmo Por lo tanto, nuestro archivo helpers.py, es un mdulo que contiene ayudantes, comunes a cualquier otro mdulo de nuestro sistema.

DOCSTRINGS Y LA FUNCIN HELP() EN PYTHON Quieres saber de qu trata el archivo helpers.py? 1. Abre una terminal 2. Navega hasta el directorio donde tienes almacenados los mdulos del sistema

3. Ejecuta el intrprete interactivo de python (escribe: python) 4. Una vez en el intrprete, escribe: 5. import helpers

help(helpers)

El "Easter Egg" de la Gua Python

Haz visto el resultado? Sorprendente! no es cierto? Los docstrings, no son algo nuevo. Ya los habamos visto al comienzo de la gua. Los Docstrings no son ms que el comentario de nuestro cdigo. Y si haz probado hacer un help(helpers), habrs podido notar la importancia de comentar nuestro cdigo. La funcin help(), al igual int(), raw_input() y tantas otras que hemos visto, es una funcin nativa de Python, es decir una funcin interna o funcin built-in. Si lo deseas, es muy recomendable ver la lista completa de las funciones built-in de Python (en ingls). help() ha sido diseada para ejecutarse en modo interactivo. Cuando le es pasado como parmetro, el nombre de un mdulo, objeto, clase, mtodo, funcin, etc., help() devolver la documentacin que hayamos especificado, as como toda informacin adicional sobre el elemento pasado como parmetro.

CONSIDERACIONES PARA ESCRIBIR DOCSTRINGS


Cuando documentes un mtodo o funcin en Python, debers escribir los docstrings teniendo en cuenta lo siguiente:

La documentacin se escribe entre triple comillas dobles en la misma lnea, justo despus de la definicin def
Correcto: def mi_funcion(): """Aqu la documentacin""" Incorrecto: def mi_funcion(): """ Aqu la documentacin """ def mi_funcion(): """ Aqu la documentacin""" Definitivamente un homicidio que amerita prisin perpetua:

def mi_funcion(): """ Aqu la documentacin """

Una buena documentacin, debe incluir la accin que realiza, lo que retorna y los parmetros que acepta.
En estos casos, se utilizan docstrings multilnea, siguiendo el prximo esquema: """Hace X retorna Y Argumentos: arg1 -- descripcin de arg1 arg2 -- descripcin de arg2 """ Las especificaciones para los docstrings se encuentran oficialmente documentadas por Python en las PEP 257.

TRABAJANDO CON FECHAS EN PYTHON


Una de las modificaciones que incorporamos hoy, consiste en gestionar las fechas de confeccin y caducidad del presupuesto, en forma automtica. Para ello, incorporamos dos helpers: def get_fecha_actual(): hoy = datetime.datetime.now() fecha_actual = hoy.strftime("%d/%m/%Y") return fecha_actual y def sumar_dias(dias=0): fecha = datetime.datetime.now() + datetime.timedelta(days=dias) nueva_fecha = fecha.strftime("%d/%m/%Y") return nueva_fecha Las fechas, podemos generarlas automticamente, gracias al mdulo datetime de Python: import datetime El mtodo now() de datetime, retorna la fecha y hora actual: hoy = datetime.datetime.now() La funcin strftime() convierte la fecha a cadena de texto, con el formato pasado como parmetro: hoy.strftime("%d/%m/%Y") Con la funcin timedelta() podemos calcular fechas, ya sea restando, como sumando, dividiendo o multiplicando N cantidad de das: fecha = datetime.datetime.now() + datetime.timedelta(days=dias)

EL MDULO DATETIME
Este mdulo, nativo de Python, nos permite realizar diferentes manejos con fechas. Para utilizar el mdulo debe importarse:
import datetime

Obtener la fecha y hora actual:


datetime.datetime.now()

Sumar, restar, multiplicar o dividir N das a una fecha:


fecha operador_aritmtico datetime.datetime.timedelta(days=N)

Donde N debe ser un nmero entero (representa la cantidad de das a sumar, restar, multiplicar o dividir). Sumar (+), Restar (-), dividir (//), multiplicar (*). Dar formato a una fecha:
fecha.strftime(string_formato)

Donde string_formato ser la cadena de texto que defina el formato deseado, con las directrices indicadas.
Para dar diversos formatos de fechas, las directrices disponibles, son las siguientes:

Chuleta para formato de fechas

REFACTORING
Hemos realizado algunos cambios a nuestro cdigo, pero que sin embargo, no se reflejan al momento de utilizar el programa.

REFACTORING

Refactoring (o refactorizacin / refactorizar) es una tcnica de programacin, que consiste en efectuar cambios al cdigo fuente, sin alterar el funcionamiento externo del programa. Qu cambios hemos hecho?
Eliminar de la clase todo aquello que no est relacionado de forma directa con la lgica propia del objeto. Para ello, recurrimos a: Refactoring #1: Eliminar la directiva print del mdulo presupuesto, movindola a un helper. Refactoring #2: Todos los textos a mostrar en los raw_input(), as como otros mensajes del sistema, fueron movidos a variables de acceso global, definidas en el archivo constantes.py. Es muy importante hacer la salvedad, de que Python, no posee el concepto de constantes como otros lenguajes. Hablar de constantes en Python, es una cuestin lingstica pero no tcnica. A los fines del lenguaje, decir constante en Python, simplemente hace referencia a variables cuyo valor, se encuentra predefinido sin necesidad de requerir modificar dinmicamente dichos datos. Limpiamos el mdulo, moviendo un mtodo genrico que podra utilizarse en cualquier otro mdulo (no necesariamente Presupuesto). Para ello, recurrimos a: Refactoring #3: mover el mtodo leer_plantilla() del mdulo Presupuesto, a un helper llamado leer_archivo() logrando que ste, pueda ser reutilizado desde cualquier otro mdulo.

TRATAMIENTO DE EXCEPCIONES: VALIDANDO LOS


DATOS INGRESADOS
Cuando se nos peda ingresar el cdigo de plan, se nos daban tres opciones: 0, 1 y 2. Pero qu suceda si por error, en vez de 0, 1 2 ingresbamos otro dato? Si ingresbamos un dato no numrico, nos generaba un error, al intentar convertirlo de literal a entero con int(). Pero, tambin poda suceder que se ingresara un nmero mayor que 2. En ese caso, la conversin a entero no fallara, pero al momento de intentar acceder al plan elegido mediante self.planes[plan_elegido] nos dara un error, ya que el ndice, estara fuera del rango de la lista. A fin de evitar estos errores, incorporamos un algoritmo de validacin, mediante eltratamiento de excepciones.

EXCEPCIONES
Una excepcin es un error inesperado que se produce durante la ejecucin de un programa.
Las excepciones en Python, cuentan con dos instancias obligatorias: try y except, donde el cdigo contenido en try intentar ejecutarse, y se falla, el error ser capturado por except, lanzando otra accin. try:

# intentar esto except: # Si lo anterior falla, capturar el error # y hacer esto otro Opcionalmente, en Python, pueden agregarse otras dos instancias, pero opcionales: else y finally. Mientras que else, se encarga de ejecutar el cdigo indicado solo si no ha fallado nada, finally, se llamar siempre (falle o no), siendo su finalidad, la de ejecutar acciones de limpieza. def probar_excepciones(): dato = raw_input("Ingresar numero para pasar, letra para fallar: ") try: int(dato) except: print "ejecutando execpt, try ha fallado" else: print "ejecutando else, try se ha logrado" finally: print "finally se ejecuta siempre" Hecha esta introduccin, vayamos a nuestro mdulo Presupuesto (lneas 53 a 63): try: elegir_plan = int(elegir_plan) self.plan = self.planes[elegir_plan] Intenta convertir a entero el plan elegido en el raw_input() y despus, intentar obtener self.planes[elegir_plan] (elegir_plan acta como nmero de ndice). Pero esta ltima, solo se llevar a cabo, si la primera, no genera una excepcin. except (ValueError, IndexError): mostrar_texto(DATO_INCORRECTO) self.seleccionar_plan() Si se genera una excepcin, se muestra un mensaje de error y se realiza una llamada recursiva. Pero Qu hay all entre parntesis? ValueError e IndexError son dos tipos de excepciones. ValueError se produce cuando el valor tratado, no corresponde al tipo de dato esperado (por ejemplo, se ingresa un caracter no numrico). E IndexError es el error lanzado cuando se intenta acceder, por ejemplo, a un tem inexistente de una lista o tupla, es decir, cuando como nmero de ndice se pasa un valor fuera del rango (es decir, mayor a la cantidad de tems en la tupla o lista). Si se desea capturar cualquier excepcin, se puede utilizar: except: Si se desea capturar nicamente un tipo de excepcin, se puede utilizar: except TipoDeExcepcion: Si se desean capturar varias excepciones en un mismo paso, se utiliza: except (TipoExcepcion1, TipoExcepcion2, TipoExcepcion5):

Es posible tambin, capturar distintas excepciones en varios pa<strongsos: except TipoExcepcion1: #... except (TipoExcepcion2, TipoExcepcion3): #... except TipoExcepcion4: #... Una alternativa muy til, es recoger la descripcin del error para poder mostrarla: except TipoExcepcion, error_capturado: print error_capturado except (TipoExcepcion1, TipoExcepcion2), error_capturado: print error_capturado Finalmente, ejecutaremos el resto del script, si ninguna excepcin ha sido lanzada: else: datos_servicio = self.lista_precios[self.planes[elegir_plan]] self.servicio = datos_servicio[0] importe = datos_servicio[1] self.importe = float(importe)

Chuleta de tipos de excepciones

WEBBROWSER: ABRIENDO EL NAVEGADOR DESDE PYTHON


# Mostrar presupuesto en navegador def mostrar_presupuesto(self, archivo): respuesta = raw_input(MOSTRAR_PRESUPUESTO) if respuesta.lower() == 's': webbrowser.open(BASE_DIR + "/" + archivo) (lneas 103 a 107) Con el mdulo webbrowser nativo de Python, es posible abrir el navegador y cargar en l, cualquier archivo HTML o direccin Web. Solo basta importar el mdulo webbrowser import webbrowser y cargar la URL mediantewebbrowser.open(URL)

UN NUEVO DESAFO
En este captulo, hemos aprendido dos conceptos fundamentales, indispensables en la vida de cualquier programador experto: la tcnica de refactoring y elmanejo de excepciones. Y ninguna de las dos, es poca cosa, ni mucho menos, pueden etiquetarse como bsicas. Los programadores que recin se inician (e incluso, puedo asegurarles que muchos programadores con aos de experiencia), no suelen refactorizar el cdigo fuente de sus programas, y son muy pocas las veces que manejan excepciones dentro del cdigo.

La tarea que nos toca hoy, es animarnos a programar como verdaderos profesionales. Cul es el desafo entonces? Hacer un refactoring de TODOS los archivos de nuestro sistema
Cmo? Muy simple. Python, tiene una serie de recomendaciones para la escritura de cdigo, llamada Style Guide for Python Code, definida en la PEP 8 de la cual hemos hablado sutilmente en captulos anteriores -. Los verdaderos programadores Python, debemos respetar esta gua de estilos al pie de la letra, ya que hacerlo, nos garantiza que nuestro cdigo pueda ser fcilmente mantenible, legible, evolutivo y por sobre todo, es una forma de respetarnos entre colegas. Escribir cdigo desprolijo o con estilo propio, dificulta la lectura. Ergo, hace que entender el cdigo escrito por otro programador, nos lleve ms trabajo. Entonces: 1. Lee las PEP 8 (en ingls) o las PEP 7 (disponibles en espaol) 2. Revisa cuidadosamente los archivos constantes.py, helpers.py y

sobre todo, presupuesto.py (tiene violaciones a las PEP 8 de forma ex-profesa) 3. Haz todas las modificaciones que sean necesarias, para estandarizar el cdigo fuente segn las PEP Si no entiendes algo de las PEP pregntalo! No te quedes con la duda. Si
te aburre, o no te apasiona hacerlo o lo consideras sin sentido, ten en cuenta que hacerlo ser fundamental para tu crecimiento profesional. Te lo garantizo!.

Es muy importante que aproveches este reto para trabajar en equipo. Puedes utilizar los comentarios para compartir con otros programadores,
las lneas de cdigo que hayas refactorizado, as como tambin, intercambiar opiniones sobre cmo sera mejor refactorizar tal o cual otra lnea. Aprovecha esto para entrenarte! La capacidad para trabajar en equipo, no solo la da la buena predisposicin, sino tambin la prctica y el intercambio con otros programadores. Y ten en cuenta, que a la hora de buscar trabajo, sumar puntos a tus fortalezas.

HERENCIA, RELACIN ENTRE DOS O MS CLASES


Y ya hemos llegado al Captulo VI de la Gua Python! En el captulo de hoy, agregaremos nueva funcionalidad a nuestro programa generador de presupuestos, introduciendo con ello, un nuevo concepto de la programacin orientada a objetos: herencia.

HERENCIA
En Programacin Orientada a Objetos, la herencia es la relacin existente entre dos o ms clases. La herencia marca una relacin de jerarqua entre objetos, en la cual, una clase principal (madre) puede ser heredada por otras secundarias (hijas), las cuales adquieren por herencia los mtodos y atributos de la primera (clase principal).
El objetivo de hoy, es utilizar esta caracterstica de la POO (la herencia), para lograr dos tipos de presupuesto: 1. El presupuesto tradicional que venimos generando. 2. Un presupuesto extendido, que emita los recibos de pagos

correspondientes, calculando el monto de adelanto y su resto.

ARCHIVOS NECESARIOS
Utilizaremos todos los archivos disponibles en la carpeta capitulo6. En esta carpeta, encontraremos las siguientes novedades:

UN NUEVO SUB-DIRECTORIO LLAMADO RECIBOS


En caso que decidamos ejecutar el generador de presupuestos en modo avanzado, ste, automticamente crear y guardar los nuevos recibos en esta carpeta.

NUEVO TEMPLATE RECIBO.TXT


Este archivo es un nuevo template, el cual emplearemos como plantilla para generar los recibos. =================================================================== ============= $titulo N $numero/1 =================================================================== ============= En $ciudad a los ___ das del mes de ___________ de 20__ RECIB de $cliente

La cantidad de $moneda $pago_1 En concepto de pago adelanto presupuesto N $numero.________________________ $nombre $web =================================================================== ============= -------------------------- >>>> cortar aqu <<<< ----------------------------=================================================================== ============= $titulo N $numero/2 =================================================================== ============= En $ciudad a los ___ das del mes de ___________ de 20__ RECIB de $cliente La cantidad de $moneda $pago_2 En concepto de pago finalizacin de obra segn presupuesto N $numero.________________________ $nombre $web =================================================================== =============

UN NUEVO MDULO: RECIBO.PY


Este ser el archivo en el que ms nos concentraremos hoy. Un modelo que hereda de Presupuesto, generando un presupuesto extendido que incluye formulario de recibo de pago. # -*- coding: utf-8 *-* from string import Template from presupuesto import Presupuesto from constantes import TEMPLATE_RECIBO, CIUDAD, MONEDA_DENOMINACION from helpers import leer_archivo class PresupuestoConRecibo(Presupuesto): def __init__(self): Presupuesto.__init__(self) self.adelanto = 40 self.titulo = "RECIBO" self.generar_recibo()

def calcular_pagos(self): """Calcula el monto correspondiente al adelanto y resto del trabajo""" total = self.neto self.pago_1 = total * self.adelanto / 100 self.pago_2 = total - self.pago_1 def generar_recibo(self): """Genera los recibos para entregar al cliente""" self.calcular_pagos() txt = leer_archivo(TEMPLATE_RECIBO) diccionario = dict(titulo=self.titulo, numero=self.numero_presupuesto, ciudad=CIUDAD, cliente=self.cliente, moneda=MONEDA_DENOMINACION, pago_1=self.pago_1, nombre=Presupuesto.encabezado_nombre, web=Presupuesto.encabezado_web, pago_2=self.pago_2) txt = Template(txt).safe_substitute(diccionario) self.guardar_recibo(txt) def guardar_recibo(self, contenido): """Guarda el recibo generado en la carpeta recibos Argumentos: contenido -- template renderizado """ filename = 'recibos/' + str(self.numero_presupuesto) + '.txt' recibo = open(filename, 'w') recibo.write(contenido) recibo.close()

RUN.PY
Este archivo, ser el que desde ahora en ms ejecutemos de la lnea de comandos en lugar de presupuesto.py. Veremos como, pasndole un parmetro determinado por lnea de comando, se encargar de ejecutar uno u otro mdulo (Presupuesto o PresupuestoConRecibo). # -*- coding: utf-8 *-* import sys from presupuesto import Presupuesto from recibo import PresupuestoConRecibo

modelo = sys.argv[1] if modelo == 'basico': presupuesto = Presupuesto() elif modelo == 'recibo': presupuesto = PresupuestoConRecibo() else: print "Argumentos no vlidos"

ESE EXTRAO ARCHIVO CON EXTENSIN .NJA


El Captulo VI de la Gua Python, lo he desarrollado con el IDE Open Source,NINJAIDE.

. El archivo Guia_Python.nja ser opcionalmente necesario, si deseas utilizar NinjaIDE para esta etapa del proyecto. El archivo .nja te evitar configurar el proyecto, pero es opcional su descarga.

ARCHIVOS MODIFICADOS presupuesto.py


Cdigo estandarizado segn PEP 8 Se elimina adems, la instancia a Presupuesto incorporndola en run.py Se limpia el mtodo __init__() Ahora, Presupuesto hereda de object (ver explicacin ms adelante)

constantes.py
- Incorpora nuevas constantes

RAZONAMIENTO LGICO DE LA HERENCIA

Como bien se coment al principio, la herencia es una de las caractersticas que define al paradigma de la Programacin Orientada a Objetos (POO), estableciendo la forma en la cual, dos o ms clases se relacionan entre s. Cuando una clase hereda de otra, sta, adquiere de forma automtica, los mtodos y atributos de la clase de la cual hereda. Existe una lgica relacional en la herencia de clases. Una clase no debe heredar al azar de otra, sino que debe existir una relacin real. Llevado a un ejemplo de la vida diaria, podramos tener una clase principal llamada Persona, que sea heredada por la clase Hombre y por la clase Mujer. Hombre y Mujer, tendran los mismos atributos que Persona (extremidades superiores, inferiores, rganos vitales), pero cada una tendra atributos propios que las distinguen entre s y a la vez extienden a Persona (rganos reproductores, genes). De la misma manera, compartiran los mismas mtodos que Persona (caminar, correr, comer), pero cada una, tendran sus propios mtodos distintivos (no, no me

pidan ejemplos, usen la imaginacin!!!!). Sin embargo, no sera relacionalmente lgico, que Perro herede de persona. Si bien puede tener atributos y mtodos que a simple vista resultan similares (correr, comer, caminar) no es una clase de Persona sino de Animal.

LA HERENCIA EN PYTHON
En Python, para indicar que una clase hereda de otra, se utiliza la siguiente sintaxis: class NombreDeLaClaseHija(NombreDeLaClaseMadre): Cuando una clase es principal (una clase madre), debe heredar de object: class Presupuesto(object): Nuestro nuevo mdulo recibo.py, hereda todos los atributos y mtodos de presupuesto: class PresupuestoConRecibo(Presupuesto): Adems, de poder definir mtodos y atributos propios que extendern las caractersticas de Presupuesto.

ACCEDIENDO A MTODOS Y ATRIBUTOS Para acceder a las propiedades de clase, es decir, aquellos atributos definidos
en la propia clase ANTES de ser instanciada, se utiliza: NombreDeLaClase.nombre_del_atributo Sin embargo, si se desea acceder a propiedades del objeto, es decir, a aquellos atributos definidos LUEGO de crear una instancia de la clase, se utiliza: self.nombre_del_atributo Es decir, que dado el siguiente cdigo: class ClaseMadre(object): atributo_de_clase = 'valor' def __init__(self): self.metodo() def metodo(self): self.atributo_del_objeto = 'otro valor' Si heredo esta clase, por otra:

class ClaseHija(ClaseMadre):
Para acceder a atributo_de_la_clase dentro de ClaseHija, tendr que hacerlo mediante: print ClaseMadre.atributo_de_la_clase Aunque tambin es posible, acceder mediante self: print self.atributo_de_la_clase Mientras que para acceder a atributo_del_objeto, primero se debe haber ejecutado el mtodo que define dicha propiedad, es decir metodo(): class ClaseHija(ClaseMadre): def __init__(self): ClaseMadre.__init__(self)

Para luego acceder a dicho atributo, mediante self: print self.atributo_del_objeto Sin embargo, podr acceder a cualquier mtodo heredado, utilizando self directamente: class ClaseMadre(object): atributo_de_clase = 'valor' def __init__(self): self.metodo() def metodo(self): self.atributo_del_objeto = 'otro valor' def segundo_metodo(self): print 'Hola Mundo' class ClaseHija(ClaseMadre): def __init__(self): ClaseMadre.__init__(self) self.otro_metodo() def otro_metodo(self): print ClaseMadre.atributo_de_clase print self.atributo_del_objeto self.segundo_metodo()

PASANDO PARMETROS A UN ARCHIVO .PY POR LNEA DE COMANDOS


Desde ahora, para ejecutar nuestro programa, ya no tendremos que hacer python presupuesto.py, sino:

python run.py argumento Donde argumento podr ser: basico, quien ejecutar el mdulo Presupuesto de la misma forma que en el Captulo V o recibo, el cual ejecutar el Presupuesto
extendido con la generacin de recibos de pago.

Si ejecutas por lnea de comandos: presupuesto run.py recibo


Al finalizar, en la nueva carpeta recibos se habr generado un TXT con el mismo nmero que el presupuesto creado, conteniendo dos recibos de pago para imprimir. En cambios, si ejecutas:

presupuesto run.py basico


No habr diferencia con lo que hemos hecho hasta el captulo anterior.

CAPTURANDO ARGUMENTOS ENVIADOS POR LNEA DE COMANDOS (EN RUN.PY)


import sys modelo = sys.argv[1]

sys es un mdulo estndar de Python que provee de funciones especficas del sistema (ampliar informacin). argv recoge una lista de parmetros que son pasados por lnea de comandos
cuanso se ejecuta mediante python archivo.py argumentos. El primer elemento de la lista argv, es decir argv[0] es el nombre del archivo. En nuestro cdigo, accedemos directamente al segundo elemento de la lista:sys.argv[1] el cul nos dir qu opcin hemos elegido. Si optamos por bsico, crearemos una instancia de Presupuesto() if modelo == 'basico': presupuesto = Presupuesto() En cambio, si hemos indicado recibo obtendremos una instancia de PresupuestoConRecibo() elif modelo == 'recibo': presupuesto = PresupuestoConRecibo() De lo contrario, se imprimir un mensaje de error: else: print "Argumentos no vlidos" Ver ms informacin sobre paso y captura de argumentos por lnea de comando.

EL DESAFO DE HOY
Nos estamos poniendo cada vez ms exigentes con nuestro cdigo. En el captulo anterior, nos toc hacer un refactoring para estandarizar el cdigo con la normativa de la PEP 8. En el captulo de hoy, el reto es doble.

DESAFO #1:
Prueba a ejecutar el mdulo run.py sin pasar ningn argumento:

python run.py Te animas a solucionar el inconveniente con la ayuda del tutorial oficial de Python? DESAFO #2
El nuevo mdulo recibo.py posee un mtodo para guardar el recibo generado, muy similar al mtodo que utiliza el mdulo Presupuesto para guardar el presupuesto en un archivo HTML. Muchas lneas de cdigo se repiten, lo cual, incurre en una redundancia innecesaria que puede ser evitada. Qu ideas se te ocurren para solucionar este cdigo redundante? No es necesario que escribas cdigo. El objetivo es que entre todos razonemos y hagamos una lluvia de ideas que nos ponga en prctica.

TESTEANDO CDIGO CON DOCTEST EN

LOS COMENTARIOS
Ya estamos llegando al final de la gua Python! En el captulo de hoy, atacaremos con una tcnica de programacin indispensable, que nos dar una gran ventaja: evitar romper el cdigo con la incorporacin de uno nuevo y prevenir bugs. Y de qu tcnica hablamos? Unit Testing o Test Unitarios.

TEST UNITARIOS
Los test unitarios representan un mecanismo indispensable, para probar el funcionamiento individual, de cada parte del cdigo, previniendo que el agregado de nuevo cdigo, haga fallar el existente.

CHANGELOG DEL CAPTULO VII


Antes de comenzar, ser necesario descargar los archivos actualizados del captulo anterior. A continuacin un resumen de los cambios que veremos: capitulo6/constantes.py Nueva constante no pblica capitulo6/helpers.py Agregados test con doctest nueva funcin para guardar archivos Refactoring: guardar_presupuesto() utiliza funcin genrica para guardar Refactoring: guardar_recibo() utiliza funcin genrica para guardar refactoring: validacin argumentos

capitulo6/presupuesto.py

capitulo6/recibo.py

capitulo6/run.py recibidos capitulo6/test/ captulo

carpeta que contiene los test del

Hoy, centraremos nuestra atencin, haciendo nfasis en los cambios realizados al archivo helpers.py. Comencemos!

DOCTEST
doctest es un mdulo nativo de Python, que busca en los comentarios de nuestro cdigo, fragmentos que se vean como sesiones del intrprete interactivo de Python, y procede a ejecutar dichos fragmentos, verificando que resulten como se le ha indicado.

Esto significa, que importando el mdulo doctest, ste, buscar en los comentarios de nuestro cdigo, todo fragmento que represente al interprete interactivo, para luego ejecutarlo. Por ejemplo: import doctest def sumar_dos_numeros(a, b): """Suma dos nmeros y retorna su resultado Argumentos: a -- primer sumando b -- segundo sumando Test: >>> sumar_dos_numeros(25, 10) 35 >>> sumar_dos_numeros(30, 20) 50 """ resultado = a + b print a + b if __name__ == "__main__": doctest.testmod() Si vemos el texto debajo de Test:, luce como el intrprete interactivo. Aqu estoy invocando a la funcin: >>> sumar_dos_numeros(25, 10) Aqu, estoy simulando el resultado que arrojara en el intrprete interactivo. Esto, ser interpretado por doctest, como el resultado esperado: 35 Y finalmente, verifico que el mdulo est siendo ejecutado como script (no importado), de ser as, doy la orden a doctest de ejecutar el script en modo test: if __name__ == "__main__": doctest.testmod()

COLOCANDO LOS DOCTEST EN UN ARCHIVO INDEPENDIENTE


En nuestro ejemplo (archivo helpers.py), sin embargo, nos encontramos con estas lneas: 74 if __name__ == "__main__": 75 doctest.testfile('tests/helpers.txt') En este caso, lo que estamos haciendo, es indicar a doctest, que nuestras pruebas se encuentran en un archivo a parte: tests/helpers.txt Si abrimos este archivo, podremos ver todos los test: 1 >>> from helpers import leer_archivo, crear_archivo, mostrar_texto 2 3 Probando leer_archivo() 4

5 >>> leer_archivo('') 6 'Error' 7 8 >>> leer_archivo('tests/archivo_de_prueba.txt') 9 'Archivo de Prueba\nHola Mundo\n' 10 11 Probando crear_archivo() 12 13 >>> crear_archivo('', 'contenido') 14 'Error' 15 >>> crear_archivo('', '') 16 'Error' 17 >>> crear_archivo('tests/archivo_de_prueba.txt', '') 18 'Error' 19 >>> crear_archivo('tests/archivo_de_prueba.txt', 'Archivo de Prueba\nHola Mundo\n') 20 21 22 Probando mostrar_texto() 23 24 >>> mostrar_texto('Hola Mundo') 25 Hola Mundo 26 >>> mostrar_texto() 25 Si te fijas las lneas resaltadas en gris, podrs ver las llamadas a los mtodos que estamos testeando. Mientras que las resaltadas en negro, simulan el resultando esperado. El texto que no aparece resaltado, es interpretado como parte de los comentarios, exceptuando la lnea 1, que se encarga de importar los mtodos a ser testeados.

EJECUTANDO LOS TEST


Una vez que el cdigo fuente cuenta con los correspondientes test, es hora de correrlos. Para ello, en la lnea de comandos, escribiremos:

python nombre_del_modulo_a_testear.py -v
En nuestro caso, navegaremos hasta la carpeta capitulo6 y escribiremos python helpers.py -v Cuando ejecutemos los test, veremos una salida similar a la siguiente: Trying: from helpers import leer_archivo, crear_archivo, mostrar_texto Expecting nothing ok Trying: leer_archivo('') Expecting: 'Error' ok Trying: leer_archivo('tests/archivo_de_prueba.txt') Expecting:

'Archivo de Prueba\nHola Mundo\n' ok Trying: crear_archivo('', 'contenido') Expecting: 'Error' ok Trying: crear_archivo('', '') Expecting: 'Error' ok Trying: crear_archivo('tests/archivo_de_prueba.txt', '') Expecting: 'Error' ok Trying: crear_archivo('tests/archivo_de_prueba.txt', 'Archivo de Prueba\nHola Mundo\n') Expecting nothing ok Trying: mostrar_texto('Hola Mundo') Expecting: Hola Mundo ok Trying: mostrar_texto() Expecting nothing ok 1 items passed all tests: 9 tests in helpers.txt 9 tests in 1 items. 9 passed and 0 failed. Test passed. En lo anterior, Trying nos describe el cdigo que se est ejecutando, mientras que Expecting, el resultado esperado. Si todo sale bien, concluir el bloque indicando ok. Al final del test, se puede acceder al reporte completo: 1 items passed all tests: 9 tests in helpers.txt 9 tests in 1 items. 9 passed and 0 failed. Test passed.

SOLUCIN DEL DESAFO DEL CAPTULO ANTERIOR


En el segundo desafo del captulo anterior, la propuesta era pensar como podra

evitarse la redundancia de cdigo, en los mtodos encargados de guardar los recibos y los presupuestos en formato HTML. Siguiendo la lnea inicial, de convertir en ayudantes genricos aquellos mtodos sin relacin directa con el compartamiento del objeto en s mismo, se cre un helper, para guardar dichos archivos: 47 def crear_archivo(ruta, contenido): 48 """crea un archivo en la ruta pasada con el contenido indicado 49 50 Argumentos: 51 ruta -- ruta al archivo. Ej. carpeta/archivo.txt 52 contenido -- template renderizado 53 54 """ 55 if not ruta or not contenido: 56 return 'Error' 57 else: 58 archivo = open(ruta, 'w') 59 archivo.write(contenido) 60 archivo.close()

ANEXO DE MATERIAL DE LECTURA COMPLEMENTARIO


El desafo de hoy, no depender de resolver un problema ni de encontrar ningn tipo de solucin puntual. El reto de hoy, consiste en desafiarte a ti mismo:

Nunca terminas de aprender y jams es suficiente lo que te ensean.


Programar, no se limita a conocer la sintaxis y funcionamiento de un lenguaje de programacin. Siempre podrs comenzar por una gua de aprendizaje, para conocer los caminos que puedes seguir, para convertirte en un verdadero profesional en determinada materia. Pero eso, no debe significarlo todo.

Solo logrars ser un experto, en el momento en el que descubras, que jams es suficiente lo que conoces y que el conocimiento no te otorga sabidura.
Tienes una alternativa: no limitar tus recursos al mero conocimiento. No acotar
tu carrera profesional al conocer sobre un lenguaje de programacin.

De tu voluntad, depender el nivel que alcances, y de tu pasin, el superarte cada da.


A continuacin, encontrars un listado de recurso, que no puedes dejar de leer. La gran mayora se encuentran en espaol. Las identificadas como indispensables, te recomiendo que hagas todo lo posible por leerlas. Las recomendadas, significa que sera una buena idea leerlas. Y las complementarias, dependern de tu curiosidad.

EL CAMINO CORRECTO
Recurre a la razn, para asimilar lo que lees. Pero recurre a tus

emociones, para saber si lo que haces, realmente te apasiona. Solo as, sabrs que ests siguiendo el camino correcto. Disfruta la lectura y apasinate practicando!

LECTURA INDISPENSABLE (ES)


Gua de aprendizaje de Python por Guido van Rossum (creador de Python) Excelente material de referencias bsicas del lenguaje. Inmersin en Python (Dive into Python) por Mark Pilgrim Excelente material para conocer a fondo el lenguaje y su aplicacin en la programacin orientada a objetos. Python no muerde por Roberto Alsina Excelente libro para aprender a razonar ms all del lenguaje.
LECTURAS RECOMENDADAS (EN ESPAOL)

Tutorial Django por @cibernatural Una muy buena gua para entender el funcionamiento del framework Django, ideal para crear aplicaciones Python Web based. Tutorial de PyGTK por John Finlay Tutorial oficial de PyGTK, una suite de mdulos Python para crear aplicaciones de escritorio con interfaces grficas GTK.
LECTURAS COMPLEMENTARIAS (EN ESPAOL)

Aprenda a Pensar como un Programador con Python por Allen Downey, Jeffrey Elkner y Chris Meyers
Un libro extenso, para leer con tiempo y calma. Muy buen material para utilizar como referencia del lenguaje. Los ltimos captulos, hacen mayor nfasis en la programacin orientada a objetos.

LECTURAS RECOMENDADAS (EN)


MySQLdb Users Guide por Andy Dustman Gua oficial de MySQLdb, interface para trabajar con bases de datos MySQL desde Python. Python doctest por Guido Van Rossum Documentacin oficial de Python doctest The PyQT Tutorial por ZetCode Tutorial sobre PyQT para crear aplicaciones de escritorio con interfaces grficas (un especial agradecimiento Jorge Courbis por pasarme el link)

QU TE GUSTARA APRENDER EN EL PRXIMO CAPTULO?


El siguiente captulo de la Gua Python te trae un desafo por adelantado. Esta vez, el tema lo elegirs t y ser sometido a votacin, mediante una encuesta. A continuacin, encontrars una brevsima introduccin a cada uno de los temas que puedes elegir en la votacin. Esta introduccin te servir para poder decidirte por uno con mayor facilidad. Recuerda que solo puedes elegir una opcin:

ACCESO A BASES DE DATOS CON MYSQLDB


2. MySQLdb es una interface para MySQL que nos permite manejar

bases de datos desde Python. Aprenderemos a conectarnos a una base de datos, leer los registros de una tabla, insertar nuevos y editar los existentes. 3. Qu necesitars para seguir este captulo? 4. Los siguientes puntos sern necesarios para entender el captulo, ya que no sern explicados: Tener MySQL instalado Conocer mnimamente la sintaxis del lenguaje SQL

TDD EN PYTHON CON UNITTEST


6. TDD (Desarrollo guiado por pruebas) y Test-First Programming, es

una tcnica de programacin que consiste en escribir tests antes de generar nuestro cdigo. Esta tcnica de programacin, es una de las ms complejas pero es la nica que garantiza un cdigo limpio, legible, estable y libre de errores. Aprenderemos conceptos bsicos sobre TDD, el algoritmo de TDD, cmo escribir tests antes de programar y ejecutar test unitarios. 7. Qu necesitars para seguir este captulo? 8. Los siguientes puntos sern necesarios para entender el captulo, ya que no sern explicados: Ganas de programar profesionalmente y estudiar algo que cuesta aprender solo.

INTERFACES GRFICAS PARA APLICACIONES DE ESCRITORIO EN PYTHON


10. Las interfaces grficas son aquellas que te permitirn desarrollar

una GUI para las aplicaciones de escritorio desarrolladas en Python, es decir, que no corrern por consola sino, en modo grfico. Veremos cmo mostrar texto, agregar un men sencillo, un campo de texto y botones con WxPython y PyQT.

11. Qu necesitars para seguir este captulo? 12. Los siguientes puntos sern necesarios para entender el captulo, ya

que no sern explicados: Nada? Ganas de ver una introduccin a interfaces grficas?

CMO VOTAR POR EL PRXIMO TEMA?


Primero, asegrate de haber ledo los detalles de cada tema en el punto anterior. Luego, dirgete a la pgina de Facebook de Maestros del Web y vota por el tema que quieres aprender.

INTERFACES GRFICAS CON WXPYTHON


A pedido popular, pues, ha sido votado por una amplia mayora y, a solo efecto de cumplir por nica vez en mi vida la voluntad de las masas, en el captulo de hoy aprenderemos veremos un ejemplo de un script Python que se ejecuta en modo grfico! OMFG! En modo GRFICO! Jesus! Tocaremos el cielo con las manos! [apagar modo irnico]

HOLA MUNDO EXTENDED


Haremos un Hola Mundo con wxPython, pero con algo ms que un simple Hola Mundo. Nuestro programa script, ser similar a un editor de textos (como el Notepad de Gindous), con la diferencia de que por defecto, nos mostrar una plantilla decarta comercial y la guardar automticamente en una carpeta destinada a almacenar todas nuestras cartas. Lo que haremos se ver as:

Para hacer este ejemplo, me inspir en la Gua oficial de Primeros Pasos con wxPython. De esta forma, ser ms simple entender la documentacin oficial.

INSTALACIN DE WXPYTHON
El primer paso, ser instalar wxPython. En Linux ser necesario el paquete: python-wxgtk2.8. En aquellos basados enDebian, basta con hacer:

sudo apt-get install python-wxgtk2.8 En Gentoo: emerge wxpython Para RedHat, Fedora, Mandriva y compaa, pueden buscar los rpm de la versin 2.8.12.0 en este enlace www.rpmfind.net/search.php?query=wxPython o
instalarlo con yum (como root):

yum install wxPython Para Windows y Mac OS Descargar instalador en www.wxpython.org/download.php

Dudas/problemas sobre instalacin: Visitarhttp:// wiki.wxpython.org/How%20to%20install%20wxPython

INTRODUCCIN
wxPython es una suite de libreras de interfaces grficas para Python
(programadas en C++), destinadas a crear GUIs de forma simple. Funciona como un mdulo ms de Python, debiendo ser importado al igual que cualquier otro. Cmo principales caractersticas de wxPython pueden citarse: 1. Portabilidad: Windows, Linux y Mac OS X 2. Apariencia: Nativa en todos los S.O. 3. Licencia: LGPL ARCHIVOS DEL EJEMPLO Para nuestro creador de cartas comerciales necesitaremos 2 archivos: constants.py editor.py Descargar ambos archivos, guardarlos en una carpeta y, dentro de esta, crear un sub-directorio llamado cartas. En este sub-directorio, se guardarn automticamente las cartas que vayamos creando. Para correrlo, simplemente haremos python editor.py y se ejecutar el script en modo grfico.

UTILIZANDO WXPYTHON EN 6 PASOS


Importar wxPython: import wx Crear una clase extendida de wx.Frame: class MiClase(wx.Frame) Crear los mtodos necesarios de la clase. Aqu, adems de definir algoritmos propios, es donde se harn las llamadas a los mtodos de wxPython y wxWidgets (ver ms adelante) 6. Finalmente, crear una instancia de wx.App: 7. app = wx.App(False) 8. Otra instancia de nuestra clase: 9. ventana = MiClase(None, Ttulo de la ventana) 10. Llamar a MainLoop del objeto app para mantener activo el programa: 11. app.MainLoop()
1. 2. 3. 4. 5.

CREANDO MTODOS DE LA CLASE


Los mtodos de la clase, lgicamente dependern de lo que queramos que nuestro programa realice. Estos mtodos variarn de acuerdo a cada programa. Lafrmula a seguir, ser recomendable que se desarrolle de la siguiente manera: DEFINIR EL MTODO __INIT__ Definir el __init__ de la clase, cuyo parmetro sea (adems de self), parent.

Esto garantizar hacer siempre una referencia al elemento parent (padre) del objeto que se est instanciando. En nuestro caso, cuando instanciamos al editor, como ventana padre le estamos indicando None (ninguna), ya que es la primera ventana que estamos instanciando:

frame = Editor(None, APP_TITLE)


En este ejemplo, adems, hay un segundo parmetro que corresponde al ttulo de la ventana. Pero ste, podramos haberlo evitado, si lo definamos directamente en el __init__. No lo hicimos, para poder extender el da de maana, este ejemplo, instanciando otras ventanas con un nombre diferente. En el __init__, adems, se debe inicializar al propio wx.Frame:

wx.Frame.__init__(self, parent, title=title, size=(800, 600))


Como se puede ver, a wx.Frame se le pueden pasar diversos parmetros. En nuestro caso, un ttulo de ventana y las medidas de la misma (ancho, alto). Es importante adems, siempre llamar al mtodo Show(), ya que de lo contrario, la ventana nunca se visualizar:

self.Show(True) Por otro lado, en el mtodo __init__ deben establecerse todas las propiedades de clase y llamar a aquellos mtodos que se encarguen de generar toda la GUI.
INCRUSTANDO WIDGETS wxPython, utiliza wxWidgets. Estos Widgets sern todos aquellos elementos que se irn incrustando en el contenedor (frame). Una lista completa de los Widgets implementados por wxPython, puede econtrarse enhttp:// docs.wxwidgets.org/2.8/wx_wxpython.html#wxpclasses.

Para utilizar cualquiera de estos Widgets, deben ser considerados como mtodos de wx, simplemente utilizando la sintaxis wx.Widget(parametros).
WIDGETS UTILIZADOS EN NUESTRO CREADOR DE CARTAS COMERCIALES

En nuestro script, los widgets utilizados son:

wx.TextCtrl()
Control de entrada de texto que permite mostrar y editar su contenido. Puede ser de una sola lnea o multilnea. Con el parmetro value se define el contenido por defecto, mientras que styledebe ser definido con las constantes de estilo del control.

wx.Menu()
Un men ya sea como lista desplegable o ventana emergente (pop-up) que permite seleccionar un elemento capturando el evento y actuando en consecuencia.

wx.MenuBar()
Una barra conteniendo una serie de mens accesibles desde la parte superior de la ventana.

wx.MessageDialog()
Un cuadro de dilogo que muestra un mensaje de una o varias lneas, con botones de opcin como Aceptar, S, No y Cancelar. Este Widget recibe como parmetros:parent la ventana padre, mensaje, titulo y estilo.

Ver lista completa de wxWidgets implementados por wxPython. LLAMANDO A LOS MTODOS HEREDADOS DE WX.FRAME

wx.Frame es una clase del mdulo wx, que hereda de otras y por lo tanto,
pone a nuestra disposicin, una larga lista de mtodos, a los cules accederemos simplemente mediante self.Metodo(). Los mtodos que utilizamos en nuestro cdigo son: wx.Frame.CreateStatusBar() Genera la barra de estado de la ventana. wx.Frame.SetMenuBar() Se encarga de crear la barra de men con todos los wxWidgets configurados. wx.EvtHandler.Bind() Captura un evento y lo enlaza a un controlador de eventos. wx.SizerFlags.Centre() Centra la ventana en el medio de la pantalla. wx.Window.Show() Muestra (u oculta) la ventana. wx.Window.Close() Cierra la ventana.

CONCLUSIN
Para utilizar cualquier interfaz grfica en Python, solo es necesario: 1. Saber Python (para programar algo y no solo mostrar ventanas

con mens, textos y botones que no hagan nada)


2. Entender la sintaxis y semntica de la programacin

orientada a objetos(para entender como funcionan las libreras grficas) 3. Tener a mano la gua de referencias de la interface grfica a utilizar(simplemente, para saber el nombre de los mtodos y objetos a los cuales recurrir, para mostrar grficamente aquello que tuvimos que programar en Python)

FINALIZANDO CON PYTHON Y MYSQL


Con el captulo de hoy, llegamos al final de esta gua. Considero que hemos aprendido muchsimas cosas de gran importancia y que no solo se han enfocado en el dominio de un lenguaje (como Python, en este caso), sino que adems, introdujeron buenas prcticas y conceptos de la programacin en general, sus diversas tcnicas y paradigmas. En este ltimo episodio, nos avocaremos a un tema particular, el cual es prcticamente imposible evitar ser abarcado en el desarrollo de un sistema informtico. Me refiero a la interaccin con bases de datos. Comencemos!

TRABAJANDO CON BASES DE DATOS MYSQL EN PYTHON


No abordaremos aqu, conocimientos bsicos sobre MySQL, uso, instalacin ni configuracin. Sin perjuicio de lo anterior, har una breve introduccin.

STRUCTURED QUERY LANGUAGE (SQL) SQL es el lenguaje de consulta estructurado utilizado para el acceso a bases de datos relacionales. Si bien SQL como lenguaje, posee ciertos estndares, el
lenguaje de consulta en s, vara para cada base de datos en particular, siendo el tratado en este ejemplo, el correspondiente a MySQL.

MYSQL MySQL es un sistema de gestin de bases de datos relacionales, libre


y que puede ser instalado en mltiples plataformas. Para seguir el captulo de esta gua, ser necesario instalar MySQL. Para ello los invito a quienes no posean MySQL instalado, que visiten el sitio de descargas de MySQL y la documentacin de MySQL.

MYSQLDB MySQLdb es una interfaz para trabajar con bases de datos MySQL desde Python. El captulo N7 de esta gua, se ha indicado como lectura recomendada, el Manual oficial de MySQLdb el cual sugiero que se lea tras
finalizar este captulo. INSTALACIN DE MYSQLDB Para interactuar desde Python con MySQL a travs de MySQLdb, es necesario instalar dicho mdulo. El nombre del paquete es python-mysqldb (por si desean instalarlo desde los repositorios), o sino, pueden descargar un tarball desdehttp://sourceforge.net/projects/mysql-python/. All mismo, encontrarn el archivoREADME con toda la informacin para instalarlo.

INTRODUCCIN A BASES DE DATOS CON PYTHON


En el caso particular de Python, el acceso a bases de datos se encuentra definido a modo de estndar en las especificaciones de DB-API (por curiosidad, puedes visitar Python Database API specification). Esto significa, que para utilizar cualquier base de datos, siempre se debern seguir los mismos pasos: 1. Importar el mdulo de conexin (en nuestro caso, utilizaremos 2. 3. 4. 5. 6. 7.

MySQLdb) import MySQLdb Conectarse a la base de datos db_host = 'localhost' usuario = 'root' clave = 'clave'

8. base_de_datos = 'mi_basededatos' 9. db = MySQLdb.connect(host=db_host, user=usuario,

passwd=clave, 10. db=base_de_datos) 11. Abrir un cursor 12. cursor = db.cursor() 13. Ejecutar una consulta
14. 15. mi_query = "SELECT campo FROM tabla WHERE campo='valor'

ORDER BY campo" 16. cursor.execute(mi_query) 17. Si se est agregando, editando o eliminando un registro: hacer un commit a la base de datos 18. db.commit() 19. Si se estn leyendo datos: obtener todos los registros hallados 20. cursor.fetchall() 21. u obtener solo el primero: 22. cursor.fetchone() 23. Cerrar el cursor abierto 24. cursor.close()

MANOS A LA OBRA!
Hecha esta introduccin, estamos en condiciones de arrancar.

CREAR LA BASE DE DATOS QUE UTILIZAREMOS


Lo primero que debemos hacer, es crear una nueva base de datos (o utilizar una existente) y ejecutar el query (consulta) que crear la tabla que utilizaremos. Para ello, abriendo una terminal accedes a MySQL escribiendo: mysql -u nombre_de_usuario_de_mysql -p contrasea_de_mysql Lgicamente, modificars nombre_de_usuario_de_mysql por tu nombre de usuario y contrasea_de_mysql por tu clave. Al pulsar la tecla enter, versmysql> Una vez all, si deseas crear una nueva base de datos, escribe: create database nombre_de_la_nueva_base_de_datos; Luego, indicamos a MySQL la base de datos que utilizaremos, escribiendo: use nombre_de_tu_base_de_datos; Habiendo indicado la base de datos a utilizar, ya ests en condiciones de ejecutar la consulta que crear la tabla. Para ejecutar la consulta, copia el siguiente query y luego pulsa la tecla enter: CREATE TABLE IF NOT EXISTS paises ( id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, pais VARCHAR(125) NOT NULL, abbr CHAR(2) NOT NULL

) ENGINE=InnoDB;

DESCARGAR ARCHIVOS
El ejemplo de este captulo, corresponde a un ABM de pases con arquitectura MVC (modelo-vista-controlador). El mismo, cuenta con los siguientes archivos: db_conn.py (Capa de abstraccin para la base de datos) pais.py (Modelo) pais_view.py (Vista) pais_controller.py (Controlador) Para ejecutar este ejemplo, llamar a pais_controller.py:

python pais_controller.py
Como podrn observar, este controlador es quien recibe las peticiones que hagamos, encargndose de realizar los cambios necesarios al modelo (la clase Pais), llamar a este modelo, y luego, enviar los datos necesarios a la vista, para que sta, finalmente, sea quien nos muestre esos datos en pantalla.

Saber ms sobre el patrn arquitectnico MVC

BALANCE FINAL DE LA GUA


As es que llegamos al final de esta gua. Queda muchsimo por aprender y sobre todo, son abundantes los consejos que podramos tomar para crecer profesionalmente. Creo, que quienes hayan seguido la gua paso a paso y participado activa o pasivamente de los comentarios de cada captulo, habrn sabido comprender las bases necesarias para no ser un programador ms. Como docente, me llevo conmigo la satisfaccin de, una vez ms, no haberme reservado lo que aprend a lo largo de mi carrera, como un secreto bajo llave, sino, el haberlo compartido con el solo objeto de ser aprovechado por quienes se sintiesen interesados, curiosos, motivados, etc. Como redactora de esta gua, quedan almacenadas en mi memoria, un cmulo de experiencias aprovechables, producto de la interaccin humana en un medio de comunicacin tan particular como lo es Internet. Y como persona, me llevo la indudable realidad sobre una educacin general en decadencia, que quisiera haber evitado conocer, pero que al mismo tiempo, me abre los ojos a un camino alternativo para cumplir mis objetivos.

Y por supuesto, para todos, un EXCELENTE 2012!

Das könnte Ihnen auch gefallen