Clases

En realidad, todo lo que estamos llamando datos en Python, son objetos. Eso quiere decir que son algo más que simplemente su valor. Poseen propiedades y métodos (también conocidos como atributos).
Puedes crearte tus propios objetos definiendo nuevos tipos de datos, las llamadas clases. Fíjate en el siguiente ejemplo:
class Silbato:
    propietario = 'policia'
    def silba(self):
        print 'piiiiiiiiiiiiiiiiiiiiiiiiiiii'
Esto define una tipo de objetos, una clase de objetos llamada silbato. Todos los objetos que definamos de este tipo, tendrán el comportamiento que hemos definido, es decir, tendrán un atributo llamado propietario y un método llamado silba(). Comprobémoslo creando uno de esos objetos:
>>> miSilbato = Silbato()
>>> miSilbato.propietario
'policia'
>>> miSilbato.silba()
piiiiiiiiiiiiiiiiiiiiiiiiiiii
Como vemos, para crear uno de tales objetos, hay que invocar el nombre de la clase como si fuera una función. Una vez hecho esto, para acceder a los atributos o a los métodos, utilizamos la misma sintaxis que con los módulos una vez importados.
Y también, para cada objeto podemos también definir nuevos atributos, usarlos y manipularlos:
>>> miSilbato.color = 'verde'
>>> miSilbato.longitud = 10
>>> miSilbato.longitud*5
50
>>> miSilbato.color
'verde'
Profundizando más, toda clase posee una serie de funciones por defecto con una utilidad muy concreta. Dichas funciones poseen nombres especiales que empiezan y acaban por la doble . Por ejemplo, la función init se ejecuta automáticamente al crear el objeto. Prueba lo siguiente:
class Saludo:
    def __init__(self):
        print 'holaaaa'

Si ahora creas un objeto de tipo saludo, automáticamente se ejecutará init y se escribirá en pantalla 'holaaaa':
>>> un_saludo = Saludo()
holaaaa
 
Esta función es, pues, muy útil para hacer todo tipo de tareas que queremos que se hagan automáticamente al crear un objeto.
Te habrá extrañado el misterioso self que aparece en los ejemplos anteriores. No te asustes: es un convenio de Python que toda función miembro de una clase tenga como primer argumento self. Eso hace referencia al propio objeto y permite a Python poder manejarlo. De forma práctica, recuerda que cuando definas una función dentro de una clase, debes poner siempre self; y cuando la uses no debes ponerlo (queda implícito).
Veamos el código de ejemplo de un programa algo más elaborado:
# -*- coding: utf-8 -*-
# Ejemplo sencillo de clases
 
class Rectangulo:
    def __init__(self, x, y):
        self.ancho = x
        self.alto = y
    def perimetro(self):
        return 2*self.ancho + 2*self.alto
    def area(self):
        return self.ancho*self.alto
 
class Cuadrado(Rectangulo):
    def __init__(self, x):
        self.ancho = x
        self.alto = x
 
 
objeto = Rectangulo(10, 20)
 
print 'Rectángulo 10x20------------------'
print 'Anchura', objeto.ancho
print 'Altura', objeto.alto
print 'Area', objeto.area()
print 'Perímetro', objeto.perimetro()
 
print 'Cuadrado 20x20--------------------'
 
objeto2 = Cuadrado(20)
 
print 'Area', objeto2.area()
print 'Perímetro', objeto2.perimetro()
 
Empecemos con el rectángulo. Fíjate que en su definición y dentro de la función init se inicializan dos variables. Ésta es la forma normal de usar variables que pertenecen a un objeto: self.nombredevariable (recuerda que self hace referencia al propio objeto). A continuación se definen dos funciones que usan esas variables, perimetro y area. Respecto del cuadrado, ¿no es cierto que no es más que un rectángulo especial, uno que tiene la misma altura que anchura? En Python se pueden definir clases derivadas de otras, sin más que poner entre paréntesis el nombre apropiado. De hecho, se llaman padres e hijas y, las clases hija, heredan las características de las clases padre. Eso lo puedes ver en el resultado de la ejecución:
Si ejecutas el código anterior, el resultado que obtendrás será el siguiente:
Rectángulo 10x20------------------
Anchura 10
Altura 20
Area 200
Perímetro 60
Cuadrado 20x20--------------------
Area 400
Perímetro 80
Primero se ha creado un Rectangulo de 10x20, de acuerdo a los valores pasados como argumentos. Luego se comprueba que todo está bien, escribiendo los valores de las propiedades del cuadrado ancho y alto. Luego se invocan las funciones miembro area y perimetro que devuelven los valores correctos. Después, se ha creado un cuadrado de tamaño 20 (de acuerdo a la definición, hay que pasarle un solo argumento que se usa y se almacena en las dos propiedades, alto y ancho). Y como un Cuadrado hereda las características de un Rectangulo (ya que la clase Cuadrado es hija de la clase Rectangulo), sin necesidad de definir nada en cuadrado, funcionan directamente area y perimetro. ¡Genial!