Skip to content

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

1
2
3
4
objet1=[un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]

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

personne=[Paul,Langevin,48]

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

personne=[Paul,Langevin,48]

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

1
2
3
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[x,x,0]

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

1
2
3
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[Paul,Langevin,48]

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

groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]

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

groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]

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

groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
groupe[2]=[Steve,Boer,22,iup2 qualite]