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 un objeto es una instancia de una clase.

  

5.1. Una clase Objet


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 de 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 por tres comillas, puede extenderse a 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 primera vista, utiliza atributos inexistentes
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

# ---------------------------------- main
# los atributos son públicos y pueden crearse 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 el 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 primera vista, 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 Personne 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 debe ser distinto de 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 agrega 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. Por lo tanto, la operación p=Personne() es equivalente a p=Persona("x", "x", 0);
  • líneas 15-9: se analiza el parámetro prenom. Debe ser no 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__ reemplaza 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 cumple la misma función que el método toString() en Java o en los lenguajes .NET;
  • líneas 41-42: manejo 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 predeterminados.

Resultados

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

5.5. Agregación de un método que funciona como un 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: pueden crearse dinámicamente
    
    # constructor
    def __init__(self,prenom="x",nom="x",age=0):
         # el nombre debe ser válido
        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 a 37. Se ha agregado el método initWithPersonne. Este invoca al constructor __init__. No es posible, como en los lenguajes tipados, tener métodos con el mismo nombre que se diferencien 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 Personne.

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 Personne 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 Personne ya está definida;
  • línea 8: declara la clase Enseignant como una clase derivada de la clase Persona;
  • línea 10: el constructor de la clase derivada Enseignant debe llamar al constructor de la clase padre Personne;
  • 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 grupo[i], como lo 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)

# ---------------------------------- principal
# 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]