Sección: python

A Python se le pasó el arroz en el ‘Desktop’

Durante mucho tiempo he deseado que la gente de Python incluyera como ‘toolkit’ para hacer ‘GUI’s wxPython, pero no. Llegó Python 3000 y han mantenido el obsoleto Tkinker.

Escribir una aplicación de escritorio con Python + wxPython es una gozada, cómodo, fácil, documentado, etc. Pero distribuirla … éso es otro cantar, sobre todo si lo haces para las tres plataformas mayoritarias (Windows, MacOSX y Linux). 

En Windows no hay Python ni wxPython, o pides que lo instalen o te curras un instalador que meta Python y todas las bibliotecas que use tu aplicación. Otro script a mantener.

En MacOSX por fortuna tenemos Python y wxPython, aunque no siempre la última versión.

En Linux es fácil instalar wxPython a través del gestor de paquetes, pero tienes que instruir al usuario cómo hacerlo si no es muy experto. También puedes encontrarte con problemas de versiones.

Es una pena. En el ’server-side’, Python ya es un lenguaje consolidado y juega en la liga de los grandes (en parte gracias a Google, que fichó a GvR y lo utilizó como base de su AppEngine).

El último invento que me lleva un tiempo sorprendiendo es Adobe Air (vale, ya sé que es propietario). Es lo que AWT y Swing debió ser y nunca llegó. El ‘runtime’ de Java es enorme. ¿Por cuánto anda ya el JRE? ¿200 Mb?

El ‘runtime’ de Air es mucho más ligero y proporciona un instalador de las aplicaciones que nos bajemos muy chulo. Por otra parte, las aplicaciones se escriben en HTML+JavaScript (o Action Script/Flash/Flex), algo que muchos desarrolladores conocen.

Es una tecnología que tengo en cuarentena, estoy leyendo, haciendo “hola mundos” y poco más, pero promete mucho.

Comentarios

Ya tenemos Python 3

Ayer, 3 de diciembre de 2008 se publicó la versión 3.0 del lenguaje de programación Python.

Esta versión aporta muchísimas novedades y muchas incompatibilidades con Python 2.x
Para ayudar en la migración de código antiguo, han desarrollado una herramienta de conversión, 2to3

Las que a mí más me han gustado:

  • Ahora sólo hay un tipo de enteros, equivalentes al antiguo long. Se acabó lo de definir los enteros “largos” con una L.
  • Se acabaron los problemas de “encoding”: el código se escribe en UTF-8 y el tipo string trabaja internamente con unicode.
  • Se ha reorganizado la librería estándar y muchos módulos obsoletos ya se han eliminado.

También hay inconvenientes: por ahora es más lento que las versiones 2.x. Nada que un buen repaso no pueda corregir.

Mi enhorabuena a toda la gente que trabaja desarrollando este lenguaje. Ha sido una decisión valiente y creo que acertada.

Comentarios

¡¡¡ Django ya es 1.0 !!!

Tras una larga espera, ya tenemos Django 1.0
Realmente la versión 0.96 se podía considerar bastante estable (creo que es la que ha utilizado Google como “inspiración” o base para montar su Google App Engine).

No voy a enumerar los cambios (para eso están las “release notes“), pero sí destacar lo que más me ha gustado por ahora:

  • Unicode: Django trabaja ahora por defecto siempre con Unicode, se acabaron los problemas con bases de datos en Latin-1 y templates en UTF-8. Todo es Unicode y basta.
  • Interfaz administrativa: ya no es necesario poner una clase anidada vacía para en el modelo. Se registra el modelo en la aplicación administrativa y listo. Mucho más limpio e intuitivo.
  • Es bastante fácil migrar una aplicación a la nueva versión.
  • El manejo de formularios es muy bueno, prácticamente no hay que hacer nada. El módulo “newforms” (0.96) ya es el definitivo.

A ver si saco tiempo y monto algo con la nueva versión …

Comentarios

Patrones de diseño para torpes – 1ª parte

Hoy hablamos de los famosos patrones de diseño o design patterns. Hay montones de libros y artículos sobre el tema, empezando por el famoso libro “Desing Patterns“, de Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides.

El caso es que no me acabo de enterar muy bien (a ratos soy un poco lerdo) y me pierdo un poco, así que he decidido explicarme a mí mismo algunos patrones de diseño típicos.

Una de las cosas que no me gustan es que las explicaciones y ejemplos que se proponen en muchos libros o artículos están relacionadas con objetos “sofware”. ¿No es acaso la programación orientada a objetos una ayuda para representar o modelizar sistemas u objetos “reales”?

Pues voy a tratar de explicar los patrones de diseño con ejemplos cotidianos, no “software”, a ver qué tal me sale.

El patrón “Factory”

Este patrón de diseño es muy útil cuando tenemos que crear (=instanciar) distintos objetos que tienen algo en común (=comparten una interfaz). Ya me he liado con tecnicismos.

Imaginemos que vamos con nuestra cámara de fotos y el coche teledirijido de nuestr@ hij@ a una tienda de electricidad para comprar pilas. El enfoque “sencillo” (=aplicando un patrón de diseño) es decirle al vendedor: “quiero pilas para estos cacharros”. El enfoque complicado (=instanciar cada objeto por separado) es decirl: “quiero pilas AAA (de 1,5 V) para la cámara, una pila de petaca de 9V para el mando y pilas AA para el cochecito”.

Analicemos el objeto demandado en cuestión: las pilas. ¿Qué caracteriza a una pila? Su voltaje, su tamaño y poco más. Es decir, las pilas tienen una interfaz común, pero son diferentes unas de otras. Si tuviésemos que modelizarlas usando clases tendríamos la clase PilaAAA, PilaPetaca, PilaAA y alguna más.

mi_pilaAAA = new PilaAAA()
mi_pilaPetaca = new PilaPetaca()
mi_pilaAA = new PilaAA()

Cada uno de estos objetos instanciados deberíamos asociarlo a su receptor:

camara_fotos.setPila(mi_pilaAAA)
mando_distancia.setPila(mi_pilaPetaca)
cochecito.setPila(mi_pilaAA)

¿No sería más cómodo tener algo (=el dependiente) que se encargase de darnos las pilas con sólo decirle para qué las queremos?

dependiente = new Dependiente()
camara_fotos.setPila(dependiente.damePilas(this))
mando_distancia.setPila(dependiente.damePilas(this))
cochecito.setPila(dependiente.damePilas(this))

Parece un gran avance, ¿no? Cada objeto cliente (la cámara, el mando a distancia y el cochecito) se despreocupan de saber qué características tienen las pilas que usan. Simplemente le piden pilas al dependiente y listo.
Es tarea del dependiente saber qué tipo de pilas tiene que devolver, y la forma de hacerlo (=implementación) es transparente para el cliente. Hoy puede que el dependiente mire un catálogo, mañana puede que consulte una base de datos y pasado mañana a lo mejor solicita un fichero XML de aparatos y pilas, pero esto no es algo que deba saber el objeto cliente.

Bien, pues simplificando bastante, el patrón “Factory” es esto mismo. Un objeto especializado se encarga de instanciar objetos para clientes, y estos utilizan los métodos que proporciona la interfaz del objeto recibido, pero sin saber nada de las interioridades del objeto, ni siquiera qué tipo de objeto es (=a partir de qué clase está instanciado).

Veamos un ejemplo un poco más “software”. Imaginemos que tenemos una clase sencilla en una aplicación de blogs que se dedica a “pintar” en pantalla el título, autor y fecha de publicación de algunos envíos.
Estos envíos pueden estar guardados en una base de datos o provenir de un RSS, por ejemplo.

A la clase cliente (la que “pinta” en pantalla”) le da igual el origen de los datos, sólo quiere los datos. Voy a poner un poco de código –utilizaré Python, que me gusta bastante ;-) y me parece muy claro.

class EnviosRSS:
    def __init__(self, url_rss):
        # Hacemos algo para traer los datos de la url
        self.post = lo_que_sea
    def dameAutor(self):
        return self.post.autor
    def dameTitulo(self):
       return self.post.titulo
    def dameFecha(self):
        return self.post.fecha

class EnviosBBDD:
    def __init__(self):
        # Hacemos algo para traer los datos de la base de datos
        self.post = lo_que_sea
    def dameAutor(self):
        return self.post.autor
   def dameTitulo(self):
        return self.post.titulo
    def dameFecha(self):
        return self.post.fecha

class EnviosFactory:
    def dameEnvios(self, url=''):
        if url == '':
           return EnviosBBDD()
        else:
           return EnviosRSS(url)
# código cliente
factory = EnviosFactory()
envios1 = factory.dameEnvios()
envios2 = factory.dameEnvios('http://davidasorey.net/index.php/feed/rss')
# pintamos los envios
print envios1.dameTitulo()
print envios1.dameAutor()
print envios1.dameFecha()
print envios2.dameTitulo()
print envios2.dameAutor()
print envios2.dameFecha()

Unas notas sobre la terminología “pythonera”: los métodos se definen con def, las clases se instancian llamando al nombre de la clase, sin new. El constructor (algo parecido, realmente) es el método __init__. Por últimos, los métodos al definirse siempre deben llevar el self por delante. Realmente Python no es un lenguaje orientado a objetos puro, pero ni falta que le hace ;-)

Para finalizar, muy importante: esto no es una lección magistral. Es mi visión personal del patrón “Factory”, que puede ser errónea e incompleta. Se admiten (se ruegan) sugerencias y comentarios.

Comentarios (6)