Introducción
Si
bien Python es un lenguaje orientado a objetos (Programación Orientada a
Objetos, POO), es posible utilizarlo sin tener en cuenta explicitamente
este hecho. Por eso se dice que Python es un lenguaje "Multi
paradigma". Los objetos ya han sido usados de manera implícita: Los
tipos de datos (str, dict, listas) son
objetos. Cada uno tiene
funciones asociadas (llamadas métodos en la jerga) y sus atributos. Por
ejemplo str.lower() devuelve un str en minúscula, porque todos los
objetos de esta clase (str) tienen el método lower() asociados.
Una
clase se puede usar para definir un tipo de datos, y si bien los tipos
de datos incluidos en Python son variados, su capacidad para hacer
representaciones (modelos) del mundo real es limitada. Es por eso que
hace falta poder definir nuestras propias clases.
Jerga de POO
Clases: Generadores de objetos
Es
una estructura que se usa como plantilla para crear objetos (de una
clase). Esta plantilla describen tanto el estado como el comportamiento
de los objetos que se crean a partir de ella. El estado es mantenido via
los atributos y el comportamiento via los métodos.
Instancia: Implementación particular de una clase
Cada
instancia es una implementación de una clase. Si tenemos la clase orca,
una instancia puede ser Willy. Es posible crear varias instancias
independientes una de otra (como Shamu que es independiente
de Willy).
Atributos (o variables de instancia): Características de los objetos
Cada
objeto tiene sus atributos, como por ejemplo peso. Willy tendrá un peso
distinto de Shamu. Aunque ambas instancias pertenecen a la misma clase
(orca). Comparten el tipo de atributo. Podriamos tener la clase perro
con instancias Lassie y Laika con el atributo color_de_pelo que no será
compartido con las instancias de la clase orca
Métodos: Comportamiento de los objetos
Un
método es una función que pertenece a una clase. Los métodos definen
como se portan los objetos derivados de una clase. La clase perro puede
tener el método ladrar. Algunos métodos pueden usar parámetros (como
ladrar(enojado)).
Herencia: Las propiedades se trasmiten de clases relacionadas
Las
clases pueden relacionarse entre ellas y no ser entidades aisladas. Es
posible tener una clase mamífero con propiedades comunes a la case orca y
la clase perro. Por ejemplo el método reproducción puede ser definido
para la clase mamífero. No sera necesario crear para ellos el método
reproducción ya que lo heredarán.
Variable de clases: caracteristicas de las clases.
Son variables asociadas a todos los objetos de una clase. Cuando un objeto es creado, el objeto hereda a variable de clase.
Polimorfismo
Es
la habilidad para los distintos objetos de responder al mismo método de
manera distinto. Es lo que permite por ejemplo al iterar sobre una
lista, un set, diccionario, archivo, etc de la misma manera:
for nombre in secuencia:
# hacer algo
Encapsulación
Ocultar la operación interna de un objeto y dar acceso a los programadores por métodos públicos. La encapsulación en Python no es total, sino mas bien nominativa (también conocida como pseudo-encapsulación). Los métodos de uso interno se marcan como tales y los programadores eligen (o no) respetar.
Creando clases
Modelo:
class NOMBRE:
[cuerpo]
Una clase que hace algo:
class Square:
def __init__(self):
self.side=1
Uso:
>>> Bob=Square() # Bob es una instancia de Square.
>>> Bob.side # Veamos el valor de side.
1
>>> Bob.side=5 # Asignar un valor nuevo a side.
>>> Bob.side # Ver el valor de side.
Este cambio es específico para una instancia, al crearse una nueva, se ejecuta __initi__ de nuevo:
>>> Krusty=Square()
>>> Krusty.side
Asignando una variable a la clase (y no solo a la instancia):
>>> class Square:
side=1
>>> Square.side
Es posible usar las variables de clases para controlar cuantas instancias de una clase han sido creadas:
class Square:
cuenta = 0
def __init__(self):
Square.cuenta += 1
print "Objecto creado OK"
Uso:
>>> Bob = Square()
"Objecto creado OK"
>>> Patricio = Square()
"Objecto creado OK"
>>> Square.cuenta
2
Ejemplo con la clase Secuencia. En biología una secuencia nucleotídica es un fragmento de ADN. Por
ejemplo: "ATGCA". Esto representa una secuencia de 5 nucleotidos (Adenina, Timina, Guanina, Citosina
y nuevamente Adenina). Esta secuencia podria ser representada como un string:
secuencia = "ATGCA"
Esta representación no nos permite almacenar funciones asociadas a este tipo de datos (métodos). Una
función propia de las secuencia es su transcripción, esto es: el proceso por el cual el ADN se convierte en
ARN. En dicha transcripción los nucleotidos se convierten siguiendo la siguiente tabla:
ADN ARN
A U
T A
C G
G C
Con estos datos podemos hacer un programa que define una clase con el métdo transcripcion:
import string
class Sequencia:
tabla = string.maketrans('ACTG','UGAC')
def __init__(self, cadena):
self.cadena = cadena.upper()
def transcripcion(self):
tt = string.translate(self.cadena,self.tabla)
return tt
miseq = Sequencia('ACAGTGTA')
print miseq.transcripcion()
Esto permite definir instancias de secuencia y luego transcribirlas:
>>> virus_peligroso = Secuencia('atggagagccttgttcttggtgtcaa')
>>> virus_peligroso.cadena
'ATGGAGAGCCTTGTTCTTGGTGTCAA'
>>> virus_peligroso.transcripcion()
'UACCUCUCGGAACAAGAACCACAGUU'
Podemos agregar entonces el método restriccion que requiere un parámetro:
def restriccion(self,enz):
if enz in Secuencia.enz_d:
return self.cadena.count(Secuencia.enz_d[enz])
else:
return 0
Herencia en acción
La herencia de una clase implica que una clase hija hereda los métodos y atributos de la clase padre. Por
ejemplo existe un tipo de secuencia de ADN denominada plásmido, que son independientes del ADN
principal (cromosómico) de la célula. Esto puede ser modelado como una clase nueva (Plasmido) que
tiene las mismas propiedades de Secuencia, mas métodos propios. En este caso se dice que la clase
Plasmido hereda de Secuencia.
Uno de los métodos que son propios de los plásmidos es la resistencia a antibioticos. El método ab_res
verifica si un plasmido particular tiene o no resistencia a un antibiotico:
class Plasmido(Secuencia):
ab_res_d = {"Tet":"CTAGCAT","Amp":"CACTACTG"}
def __init__(self,cadena):
Secuencia.__init__(self,cadena)
def ab_res(self,ab):
if ab in self.ab_res_d and self.ab_res_d[ab] in self.cadena:
return True
else:
return False
Resultado:
>>> x5 = Plasmido('TACGTCACTACTGAG')
>>> x5.ab_res('Amp')
True
REFERENCIAS
• Python Programming/OOP: en.wikibooks.org/wiki/Python_Programming/OOP.
• Introduction to OOP with Python: www.voidspace.org.uk/python/articles/OOP.shtml.
• Dive into Python. Capítulo 5. diveintopython.org/object_oriented_framework.