5. Las clases y los objetos
La clase es el molde a partir del cual se crean los objetos. Se dice que el objeto es una instancia de una clase.
![]() |
5.1. Una clase Objeto
Programa (classes_01)
# -*- coding=utf-8 -*-
class Objet:
"""une classe Objet vide"""
# cualquier variable puede tener atributos por definición
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
# muestra el objeto
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# modifica el objeto
obj1.attr2+=100
# muestra el objeto
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# asigna la referencia objeto1 a objeto2
obj2=obj1
# modifica obj2
obj2.attr2=0
# muestra los dos objetos
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)
Notas:
- línea 4: otra forma de comentario. Este, precedido de tres «, puede extenderse a lo largo de varias líneas;
- líneas 3-4: una clase de objeto vacía;
- línea 7: instanciación de la clase Objet;
- línea 17: copia de referencias. Las variables obj1 y obj2 son dos punteros (referencias) a un mismo objeto.
Resultados
5.2. Una clase Persona
Programa (classes_02)
# -*- coding=utf-8 -*-
class Personne:
# atributos de la clase
# no declarados: se pueden crear dinámicamente
# método
def identite(self):
# a priori, utiliza atributos inexistentes
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# los atributos son públicos y se pueden crear dinámicamente
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
# llamada a un método
print "personne={0}\n".format(p.identite())
Notas:
- líneas 3-10: una clase con un método;
- línea 8: todo método de una clase debe tener como primer parámetro el objeto self, que designa al objeto actual.
Resultados
5.3. La clase Persona con un constructor
Programa (classes_03)
# -*- coding=utf-8 -*-
class Personne:
# constructor
def __init__(self,prenom,nom,age):
self.prenom=prenom;
self.nom=nom;
self.age=age;
# método
def identite(self):
# a priori, utiliza atributos inexistentes
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# un objeto Persona
p=Personne("Paul","Langevin",48)
# llamada a un método
print "personne={0}\n".format(p.identite())
Notas:
- línea 6: el constructor de una clase se llama __init__. Al igual que con los demás métodos, su primer parámetro es self;
- línea 18: se crea un objeto Persona con el constructor de la clase.
Resultados
5.4. La clase Persona con controles de validez en el constructor
Programa (classes_04)
# -*- coding=utf-8 -*-
import re
# -------------------
# una clase de excepción propia
class MyError(Exception):
pass
class Personne:
# constructor
def __init__(self,prenom="x",nom="x",age=0):
# el nombre no debe estar vacío
match=re.match(r"^\s*(\S+)\s*$",prenom)
if not match:
raise MyError("Le prenom ne peut etre vide")
else:
self.prenom=match.groups()[0]
# el apellido no debe estar vacío
match=re.match(r"^\s*(\S+)\s*$",nom)
if not match:
raise MyError("Le nom ne peut etre vide")
else:
self.nom=match.groups()[0]
# la edad debe ser válida
match=re.match(r"^\s*(\d+)\s*$",str(age))
if not match:
raise MyError("l'age doit etre un entier positif")
else:
self.age=match.groups()[0]
def __str__(self):
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- mano
# un objeto Persona
try:
p=Personne(" Paul "," Langevin ",48)
print "personne={0}".format(p)
except MyError, erreur:
print erreur
# otro objeto Persona
try:
p=Personne(" xx "," yy "," zz")
print "personne={0}".format(p)
except MyError, erreur:
print erreur
# otra persona
try:
p=Personne()
print "personne={0}".format(p)
except MyError, erreur:
print erreur
Notas:
- líneas 7-8: una clase MyError derivada de la clase Exception. No añade ninguna funcionalidad a esta última. Solo está ahí para tener una excepción propia;
- línea 13: el constructor tiene valores por defecto para sus parámetros. Así, la operación p=Personne() es equivalente a p=Personne("x","x",0);
- líneas 15-9: se analiza el parámetro prenombre. Debe ser distinto de vacío. Si no es así, se lanza la excepción MyError con un mensaje de error;
- líneas 21-25: lo mismo para el nombre;
- líneas 27-31: verificación de la edad;
- líneas 33-34: la función __str__ sustituye al método que antes se llamaba identite;
- líneas 38-42: instanciación de una persona y posterior visualización de su identidad;
- línea 39: instanciación;
- línea 40: visualización. La operación solicita que se muestre la persona p en forma de cadena de caracteres. El intérprete de Python llama entonces automáticamente al método p.__str__() si existe. Este método desempeña la misma función que el método toString() en Java o en los lenguajes .NET;
- líneas 41-42: gestión de una posible excepción de tipo MyError. A continuación, muestra el mensaje de error asociado a la excepción;
- líneas 44-48: lo mismo para una segunda persona instanciada con parámetros erróneos;
- líneas 50-54: lo mismo para una tercera persona instanciada con los parámetros por defecto.
Resultados
5.5. Se añade un método que actúa como segundo constructor
Programa (classes_05)
# -*- coding=utf-8 -*-
import re
# -------------------
# una clase de excepción propietaria
class MyError(Exception):
pass
class Personne:
# atributos de la clase
# no declarados: se pueden crear dinámicamente
# constructor
def __init__(self,prenom="x",nom="x",age=0):
# el nombre no puede estar vacío
match=re.match(r"^\s*(\S+)\s*$",prenom)
if not match:
raise MyError("Le prenom ne peut etre vide")
else:
self.prenom=match.groups()[0]
# el apellido no debe estar vacío
match=re.match(r"^\s*(\S+)\s*$",nom)
if not match:
raise MyError("Le nom ne peut etre vide")
else:
self.nom=match.groups()[0]
# la edad debe ser válida
match=re.match(r"^\s*(\d+)\s*$",str(age))
if not match:
raise MyError("l'age doit etre un entier positif")
else:
self.age=match.groups()[0]
def initWithPersonne(self,p):
# inicializa el objeto actual con una persona p
self.__init__(p.prenom,p.nom,p.age)
def __str__(self):
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# un objeto Persona
try:
p0=Personne(" Paul "," Langevin ",48)
print "personne={0}".format(p0)
except MyError, erreur:
print erreur
# otro objeto Persona
try:
p1=Personne(" xx "," yy "," zz")
print "personne={0}".format(p1)
except MyError, erreur:
print erreur
# otra persona
p2=Personne()
try:
p2.initWithPersonne(p0)
print "personne={0}".format(p2)
except MyError, erreur:
print erreur
Notas:
- la diferencia con el script anterior se encuentra en las líneas 35-37. Se ha añadido el método initWithPersonne. Este utiliza el constructor __init__. No es posible, como en los lenguajes tipados, tener métodos con el mismo nombre diferenciados por la naturaleza de sus parámetros o de su resultado. Por lo tanto, no es posible tener varios constructores que construyan el objeto a partir de parámetros diferentes, en este caso un objeto de tipo Persona.
Resultados
5.6. Una lista de objetos Persona
Programa (classes_06)
# -*- coding=utf-8 -*-
class Personne:
...
# ---------------------------------- main
# creación de una lista de objetos persona
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
# identidad de estas personas
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
Notas:
- líneas 3-5: la clase Persona ya descrita
Resultados
5.7. Creación de una clase derivada de la clase Persona
Programa (classes_07)
# -*- coding=utf-8 -*-
import re
class Personne:
...
class Enseignant(Personne):
def __init__(self,prenom="x",nom="x",age=0,discipline="x"):
Personne.__init__(self,prenom,nom,age)
self.discipline=discipline
def __str__(self):
return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.discipline)
# ---------------------------------- mano
# creación de una lista de objetos «Persona» y derivados
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
# identidad de estas personas
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
Notas:
- líneas 5-6: la clase Persona ya definida;
- línea 8: declara la clase Profesor como una clase derivada de la clase Persona;
- línea 10: el constructor de la clase derivada Profesor debe llamar al constructor de la clase padre Persona;
- líneas 21-22: para mostrar grupo[i], el intérprete utiliza el método grupo[i].__str__(). El método __str__() utilizado es el de la clase real de groupe[i], tal y como muestran los resultados a continuación.
Resultados
5.8. Creación de una segunda clase derivada de la clase Persona
Programa (classes_08)
# -*- coding=utf-8 -*-
import re
class Personne:
...
class Enseignant(Personne):
...
class Etudiant(Personne):
def __init__(self,prenom="x",nom="x",age=0,formation="x"):
Personne.__init__(self,prenom,nom,age)
self.formation=formation
def __str__(self):
return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.formation)
# ---------------------------------- mano
# creación de una lista de objetos Persona y derivados
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
# identidad de estas personas
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
Notas:
- este script es similar al anterior.
Resultados
