Python/Introducción
Python fue creado como sucesor del lenguaje ABC por Guido van Rossum en 1990 cuando trabajaba en el Stichting Mathematisch Centrum (CWI). En 1995 Guido continuó su trabajo en Python en el CNRI donde creó muchas versiones del lenguaje.
En mayo del 2000 Guido y el equipo de desarrollo de Python se trasladan a BeOpen.com y se forma el BeOpen PythonLabs. En octubre de este mismo año, PythonLabs se va a Digital Creations (actualmente Zope Corporation). En 2001, se crea la Python Software Foundation (PSF), una organización sin ánimo de lucro creada específicamente para proteger la libertad de Python como lenguaje de código abierto.
El nombre del lenguaje proviene de la afición de su creador original, Guido van Rossum, por los geniales humoristas británicos Monty Python.
Python ha sido usado para crear programas tan famosos como el gestor de listas de correo Mailman y los gestores de contenido Zope y Plone.
En este wikilibro los ejemplos están creados de la siguiente manera: El texto escrito en negrita es la parte que escribe el programador en la linea de órdenes, y el texto escrito normal es el texto que devuelve el interprete.
Los programas de ejemplo de este libro son software libre; pueden ser redistribuidos y modificados según los términos de la licencia de Python publicada por la Python Software Foundation.
Tutorial
[editar]- Instalación de Python en Windows
- Abre un explorador web y entra a [1].
- Haz clic en el link “Download”
- Deberías ver muchos links, con nombres como “Python 2.6.2” y “Python 2.6.2 Windows Installer”. Haz click en el link “Windows Installer” – debería darte el instalador directamente.
- Sigue las instrucciones para los usuarios de Windows. Esto comenzará la descarga de un archivo llamado python-2.6.2.msi (o algo similar).
- Almacena el instalador para Windows en alguna carpeta de tu computadora.
- Haz doble-clic en el archivo que descargaste. Esto inicia la interfaz de instalación de Python, la cual es muy fácil de usar. Acepta la configuración que te ofrece como predeterminado, espera que la instalación finalice y estás listo para comenzar.
Asumiendo que todo se desarrolló sin problemas, ahora tienes un nuevo programa en tu menú de inicio de Windows. Corre el ambiente de desarrollo integrado de Python (IDLE) seleccionando Start > Programs > Python > IDLE (Python GUI).
Python posee un intérprete interactivo que permite imprimir texto, realizar operaciones aritméticas, asignación de variables, etc.
Programa Hola Mundo
[editar]x = "Hola Mundo"
print x
Declaración e inicialización de Variables
[editar]Las variables no tienen tipo, así que no hay que declararlas. Aparecen cuando se les asigna algo y desaparecen al dejar de usarlas. La asignación se realiza mediante el operador =. Para comprobar la igualdad se utiliza el operador == . Se puede asignar varias variables a la vez:
Edad = 20
x,y,z = 1,2,3
primero, segundo = segundo, primero
a = b = 123
Implementación y uso de la Programación Orientada a Objetos
[editar]Python es un lenguaje de programación con un enfoque multiparadigma y proporciona mucha libertad.
Una de las características de python es que también es orientado a objetos. Esto nos permite declarar e instanciar clase que nos sirvan de apoyo en nuestra programación mediante clases.
Las clases permiten agrupar en un nuevo tipo los datos y las funcionalidades asociadas a dichos datos. Las clases no se manipulan directamente sino que sirven para la definición nuevos tipos. Una clase define propiedades y comportamiento que se muestran en los entes llamados objetos (o instancias de una clase). La clase actúa como molde de un conjunto de objetos, de los que se dice que pertenecen a la clase.
- Definición e Instanciación
Las clases en Python tienen la siguiente estructura:
class NombreClase:
<instruccion_1>
.........
<instruccion_2>
la palabra reservada "class" nos indica que estamos declarando una nueva clase, la palabra NombreClase es la etiqueta de dicha clase, los dos puntos(:) nos dice que empieza el bloque de instrucciones. un ejemplo:
class Fecha:
"Ejemplo de clase para representar fechas"
dia = 28
mes = "Julio"
anio = 2009
def dime_fecha(self):
return "%i de %s de %i" % (Fecha.dia, Fecha.mes, Fecha.anio)
mi_fecha = Fecha()
print mi_fecha.dia, mi_fecha.mes, mi_fecha.anio
print mi_fecha.dime_fecha()
Definimos la clase Fecha y luego se le asigna valores a los atributos dia, mes, anio y definimos la función dime_fecha. Luego en algún lugar fuera de la definición de la clase instanciamos un objeto clase Fecha. La siguiente instrucción lo que haces es que manda a llamar cada atributo de la clase fecha para crear un pseudo print y el siguiente utiliza la función que ya trae la clase.
- Comportamiento de Objetos
Dos objetos creados con la misma definición de una clase son entidades distintas.
>>> fecha1= Fecha()
>>> fecha2 = Fecha()
>>> fecha1 is fecha2
False
>>> print fecha1
<__main __.Fecha instance at 0x00B184B8>
>>> print fecha2
<__main __.Fecha instance at 0x00B18328>
Como podrán ver cada una tiene su propio espacio de memoria reservado y ambas están instanciadas en el módulo main. Y al ser esto así se puede mandar a llamar las funciones o atributos que tengan cada una declarados.
- Esquema de administración y separación de la memoria
El manejo de memoria involucra un heap privado en el cual se encuentran todos los objetos y estructuras. El manejo de este heap es resguardado internamente por el Python Memory Manager. Tiene varios componentes que ayudan a lidiar con varios aspectos de almacenado dinamico, como compartimiento, segmentacion y caching.
En el más bajo nivel, un asignador de memoria cruda se asegura de que haya suficiente espacio para guardar toda la data relacionada con Python al interactuar con el manejador de memoria del sistema operativo. Encima del asignador de memoria cruda, varios asignadores objeto-específico operan en el mismo heap e implementan distintas pólizas de manejo de memoria adaptadas a la peculiaridad de cada tipo de objeto. Por ejemplo, objetos de tipo entero son manejados distintamente a los objetos de tipo string, tuplas o diccionarios porque enteros implican diferente requerimiento de almacenado y compensaciones de espacio y velocidad. Por esta razón el manejador de memoria de Python delega algunos trabajos a los asignadores objeto específico, pero se asegura que operen dentro del mismo heap privado.
Es importante entender que el manejo de memoria de Python en el heap es hecho por el intérprete y que el usuario no tiene control sobre él. La asignación del espacio en el heap y otros buffers internos es realizada por el manejador de memoria de Python mediante el API Python/C.
Para evitar corrupción de memoria, escritores de extension no debería operar en los objetos de Python usando las funciones exportadas de la librería de C: malloc,calloc,realloc y free. Es resultara en llamado cruzados entre asignadores de C y el controlador de memoria de Python, porque implementan algoritmos diferentes y operan en heaps distintos. Sin embargo, una manera segura de asignar y soltar bloques de memoria con el C library allocator es demostrado con el siguiente ejemplo:
PyObject *res;
char *buf = (char *) malloc(BUFSIZ); /* for I/O */
if (buf == NULL)
return PyErr_NoMemory();
...Do some I/O operation involving buf...
res = PyString_FromString(buf);
free(buf); /* malloc'ed */
return res;
En este ejemplo, la petición de memoria para el buffer I/O es manejado por el C library allocator. El administrador de memoria de Python se ve solamente involucrado con la asignación del objeto string que es retornado como resultado.
En muchas situaciones, sin embargo,es recomendado que se asigne memoria del heap privado de Python porque esa parte esta bajo control del administrador de memoria de Python. Por ejemplo, es requerido cuando el intérprete se extiende con nuevos tipos de objeto escritos en C. Otra razón por la cual usar el heap de Python es recomendado es cuando se desea informar al AMP acerca de las necesidades de memoria del modulo de extension. Incluso cuando la memoria solicitada es usada exclusivamente para propósitos altamente específicos e internos, delegando todas las solicitudes de memoria al AMP hace que el intérprete tenga una imagen mas clara de sus huellas de memoria como conjunto. Consecuentemente, bajo ciertas circunstancias, el AMP puede o no disparar acciones apropiadas, como recolección de basura, compactación de memoria u otras medidas preventivas. Nótese que al usar el C library allocator mostrado en el primer ejemplo, la memoria asignada para el buffer I/O se escapa completamente el AMP.
Implementación de Co-rutinas
[editar]Una corutina es una subrutina que retorna al llamador antes de completar su proceso. En realidad las subrutinas son un tipo de corutina que solo retornan una sola vez. En teoría los generadores de python son semi-corutinas, porque el llamador no le puede inyectar datos al generador.
Esto se podría cambiar mediante:
def generador(): def corutina(): a = 0 a = 0 yield a + 10 vs. a = yield a + 10 yield a + 10 a = yield a + 10 yield a + 10 a = yield a + 10
for x in generador(): for x in corutina(): print x print x continue continue x + 1
El caso del generador imprime 10, 10 y 10. El continue de la izquierda no hace falta pero lo pongo por simetría.
Una imaginaria implementación en python podría permitir poner una expresión luego del continue. El resultado de esa expresión sería el valor retornado por yield. En este supuesto caso imprimiría: 10, 21 y 32.
Aún así para que las corutinas sean completas el llamador no debe tener una "jerarquía" especial. Es decir que una corutina pueda llamar a otra ("collamada".)
Manejo de Excepciones
[editar]Las excepciones son errores detectados por Python durante la ejecución del programa. Cuando el intérprete se encuentra con una situación excepcional, como el intentar dividir un número entre 0 o el intentar acceder a un archivo que no existe, este genera o lanza una excepción, informando al usuario de que existe algún problema.
Si la excepción no se captura el flujo de ejecución se interrumpe y se muestra la información asociada a la excepción en la consola de forma que el programador pueda solucionar el problema.
En Python se utiliza una construcción try-except para capturar y tratar las excepciones. El bloque try (intentar) define el fragmento de código en el que creemos que podría producirse una excepción. El bloque except (excepción) permite indicar el tratamiento que se llevará a cabo de producirse dicha excepción. Muchas veces nuestro tratamiento de la excepción consistirá simplemente en imprimir un mensaje más amigable para el usuario, otras veces nos interesará registrar los errores y de vez en cuando podremos establecer una estrategia de resolución del problema.
En el siguiente ejemplo intentamos crear un objeto f de tipo fichero. De no existir el archivo pasado como parámetro, se lanza una excepción de tipo IOError, que capturamos gracias a nuestro try-except.
try:
f = file("archivo.txt")
except:
print "El archivo no existe"
Python permite utilizar varios except para un solo bloque try, de forma que podamos dar un tratamiento distinto a la excepción dependiendo del tipo de excepción de la que se trate. Esto es una buena práctica, y es tan sencillo como indicar el nombre del tipo a continuación del except.
try:
num = int("3a")
print no_existe
except NameError:
print "La variable no existe"
except ValueError:
print "El valor no es un numero"
Cuando se lanza una excepción en el bloque try, se busca en cada una de las cláusulas except un manejador adecuado para el tipo de error que se produjo. En caso de que no se encuentre, se propaga la excepción.
Además podemos hacer que un mismo except sirva para tratar más de una excepción usando una tupla para listar los tipos de error que queremos que trate el bloque:
try:
num = int("3a")
print no_existe
except (NameError, ValueError):
print "Ocurrio un error"
La construcción try-except puede contar además con una cláusula else, que define un fragmento de código a ejecutar sólo si no se ha producido ninguna excepción en el try.
try:
num = 33
except:
print "Hubo un error!"
else:
print "Todo esta bien"
También existe una cláusula finally que se ejecuta siempre, se produzca o no una excepción. Esta cláusula se suele utilizar, entre otras cosas, para tareas de limpieza.
try:
z = x / y
except ZeroDivisionError:
print "Division por cero"
finally:
print "Limpiando…"
También es interesante comentar que como programadores podemos crear y lanzar nuestras propias excepciones. Basta crear una clase que herede de Exception o cualquiera de sus hijas y lanzarla con raise.
class MiError(Exception):
def __init__(self, valor):
self.valor = valor
def __str__(self):
return "Error " + str(self.valor)
try:
if resultado > 20:
raise MiError(33)
except MiError, e:
print e
Por último, a continuación se listan las excepciones disponibles por defecto, así como la clase de la que deriva cada una de ellas entre paréntesis.
- BaseException: Clase de la que heredan todas las excepciones.
- Exception(BaseException): Super clase de todas las excepciones que no sean de salida.
- GeneratorExit(Exception): Se pide que se salga de un generador.
- StandarError(Exception): Clase base para todas las excepciones que no tengan que ver con salir del intérprete.
- ArithmeticError(StandardError): Clase base para los errores aritméticos.
- FloatingPointError(ArithmeticError): Error en una operación de coma flotante.
- OverflowError(ArithmeticError): Resultado demasiado grande para poder representarse.
- ZeroDivisionError(ArithmeticError): Lanzada cuando el segundo argumento de una operación de división o módulo era 0
- AssertionError(StandardError): Falló la condición de un estamento assert.
- AttributeError(StandardError): No se encontró el atributo.
- EOFError(StandardError): Se intentó leer más allá del final de fichero.
- EnvironmentError(StandardError): Clase padre de los errores relacionados con la entrada/salida.
- IOError(EnvironmentError): Error en una operación de entrada/salida.
- OSError(EnvironmentError): Error en una llamada a sistema.
- WindowsError(OSError): Error en una llamada a sistema en Windows.
- ImportError(StandardError): No se encuentra el módulo o el elemento del módulo que se quería importar.
- LookupError(StandardError): Clase padre de los errores de acceso.
- IndexError(LookupError): El índice de la secuencia está fuera del rango posible.
- KeyError(LookupError): La clave no existe.
- MemoryError(StandardError): No queda memoria suficiente.
- NameError(StandardError): No se encontró ningún elemento con ese nombre.
- UnboundLocalError(NameError): El nombre no está asociado a ninguna variable.
- ReferenceError(StandardError): El objeto no tiene ninguna referencia fuerte apuntando hacia él.
- RuntimeError(StandardError): Error en tiempo de ejecución no especificado.
- NotImplementedError(RuntimeError): Ese método o función no está implementado.
- SyntaxError(StandardError): Clase padre para los errores sintácticos.
- IndentationError(SyntaxError): Error en la indentación del archivo.
- TabError(IndentationError): Error debido a la mezcla de espacios y tabuladores.
- SystemError(StandardError): Error interno del intérprete.
- TypeError(StandardError): Tipo de argumento no apropiado.
- ValueError(StandardError): Valor del argumento no apropiado.
- UnicodeError(ValueError): Clase padre para los errores relacionados con unicode.
- UnicodeDecodeError(UnicodeError): Error de decodificación unicode.
- UnicodeEncodeError(UnicodeError): Error de codificación unicode.
- UnicodeTranslateError(UnicodeError): Error de traducción unicode.
- StopIteration(Exception): Se utiliza para indicar el final del iterador.
- Warning(Exception): Clase padre para los avisos.
- DeprecationWarning(Warning): Clase padre para avisos sobre características obsoletas.
- FutureWarning(Warning): Aviso. La semántica de la construcción cambiará en un futuro.
- ImportWarning(Warning): Aviso sobre posibles errores a la hora de importar.
- PendingDeprecationWarning(Warning): Aviso sobre características que se marcarán como obsoletas en un futuro próximo.
- RuntimeWarning(Warning): Aviso sobre comportmaientos dudosos en tiempo de ejecución.
- SyntaxWarning(Warning): Aviso sobre sintaxis dudosa.
- UnicodeWarning(Warning): Aviso sobre problemas relacionados con Unicode, sobre todo con problemas de conversión.
- UserWarning(Warning): Clase padre para avisos creados por el programador.
- KeyboardInterrupt(BaseException): El programa fue interrumpido por el usuario.
- SystemExit(BaseException): Petición del intérprete para terminar la ejecución.
Ejemplos del Lenguaje
[editar]1) Raíz cuadrada de un número.
from math import sqrt
for n in range(99, 0, -1):
root = sqrt(n)
if root == int(root):
print n
break
2) Abrir un archivo y leer carácter por carácter.
file = open('test.txt', 'r')
print file.read()
while 1:
char = file.read(1) # read by character
if not char: break
print char,
file.close()
3) Una función recibe una cadena y la imprime
def bienvenido(nombre):
print "\t\Bienvenido a casa!\n"
print "\t\t", title, "\n"
bienvenido("Andres")
4) Simple Manejo de Excepción
number1 = raw_input( "Enter numerator: " )
number2 = raw_input( "Enter denominator: " )
try:
number1 = float( number1 )
number2 = float( number2 )
result = number1 / number2
# float raises a ValueError exception
except ValueError:
print "You must enter two numbers"
except ZeroDivisionError:
print "Attempted to divide by zero"
else:
print "%.3f / %.3f = %.3f" % ( number1, number2, result )
5) Una calculadora simple.
from Tkinter import *
def frame(root, side):
w = Frame(root)
w.pack(side=side, expand=YES, fill=BOTH)
return w
def button(root, side, text, command=None):
w = Button(root, text=text, command=command)
w.pack(side=side, expand=YES, fill=BOTH)
return w
class Calculator(Frame):
def __init__(self):
Frame.__init__(self)
self.option_add('*Font', 'Verdana 12 bold')
self.pack(expand=YES, fill=BOTH)
self.master.title('Simple Calculator')
self.master.iconname("calc1")
display = StringVar()
Entry(self, relief=SUNKEN,
textvariable=display).pack(side=TOP, expand=YES,
fill=BOTH)
for key in ("123", "456", "789", "-0."):
keyF = frame(self, TOP)
for char in key:
button(keyF, LEFT, char,
lambda w=display, c=char: w.set(w.get() + c))
opsF = frame(self, TOP)
for char in "+-*/=":
if char == '=':
btn = button(opsF, LEFT, char)
btn.bind('<ButtonRelease-1>',
lambda e, s=self, w=display: s.calc(w), '+')
else:
btn = button(opsF, LEFT, char,
lambda w=display, s=' %s '%char: w.set(w.get()+s))
clearF = frame(self, BOTTOM)
button(clearF, LEFT, 'Clr', lambda w=display: w.set(''))
def calc(self, display):
try:
display.set('eval(display.get())')
except:
display.set("ERROR")
if __name__ == '__main__':
Calculator().mainloop()
6. Implementación del logaritmo binario.
El valor numérico del logaritmo binario de un número real positivo puede ser calculado fácilmente utilizando este algoritmo escrito en lenguaje Python.[1]
#!/usr/bin/python
from __future__ import division
def log2(X):
epsilon = 1.0/(10**12)
integer_value=0
while X < 1:
integer_value = integer_value - 1
X = X * 2
while X >= 2:
integer_value = integer_value + 1
X = X / 2
decfrac = 0.0
partial = 0.5
X=X*X
while partial > epsilon:
if X >= 2:
decfrac = decfrac + partial
X = X / 2
partial = partial / 2
X=X*X
return (integer_value + decfrac)
if __name__ == '__main__':
value = 4.5
print " X =",value
print "LOG2(X) =",log2(value)
# Ejemplo
#
# $ python log2.py
# X = 4.5
# LOG2(X) = 2.16992500144
#
Bibliografia
[editar]- Python How To Program
- Beginning Python - From Novice To Professional (2005)