Skip to content

5. Classes and Objects

A class is the template from which objects are created. An object is said to be an instance of a class.

  

5.1. An Object Class


Program (classes_01)

#   -*- coding=utf-8 -*-

class Objet:
    """une classe Objet vide"""

#   any variable can have attributes by construction
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
#  displays the
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
#   modify object
obj1.attr2+=100
#  displays the
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
#   assigns object1 reference to object2
obj2=obj1
#   modify obj2
obj2.attr2=0
#   displays both objects
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)

Notes:

  • line 4: another form of comment. Preceded by three "", it can span multiple lines;
  • lines 3-4: an empty object class;
  • line 7: instantiation of the Object class;
  • line 17: reference copying. The variables obj1 and obj2 are two pointers (references) to the same object.

Results

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

5.2. A Person class


Program (classes_02)

#    -*- coding=utf-8 -*-

class Personne:
    #    class attributes
    #    undeclared - can be created dynamically

    #    method
    def identite(self):
        #    a priori, uses non-existent attributes
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

#    ---------------------------------- main
#  attributes are public and can be created dynamically
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
#    method call
print "personne={0}\n".format(p.identite())

Notes:

  • lines 3-10: a class with a method;
  • Line 8: Every method in a class must have the self object—which refers to the current object—as its first parameter.

Results

personne=[Paul,Langevin,48]

5.3. The Person class with a constructor


Program (classes_03)

#   -*- coding=utf-8 -*-

class Personne:

    #   manufacturer
    def __init__(self,prenom,nom,age):
        self.prenom=prenom;
        self.nom=nom;
        self.age=age;

    #   method
    def identite(self):
        #   a priori, uses non-existent attributes
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

#   ---------------------------------- main
#   a Person object
p=Personne("Paul","Langevin",48)
#   method call
print "personne={0}\n".format(p.identite())

Notes:

  • line 6: the class constructor is called __init__. As with other methods, its first parameter is self;
  • line 18: A Person object is created using the class constructor.

Results

personne=[Paul,Langevin,48]

5.4. The Person class with validity checks in the constructor


Program (classes_04)

#    -*- coding=utf-8 -*-

import re

# -------------------
#    a proprietary exception class
class MyError(Exception):
    pass

class Personne:

    #    manufacturer
    def __init__(self,prenom="x",nom="x",age=0):
         #  first name must be non-empty
        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]
        #  name must be non-empty
        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]
        #  age must be valid
        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)

#    ---------------------------------- main
#    a Person object
try:
    p=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
#    another object Nobody
try:
    p=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
#    another person
try:
    p=Personne()
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur

Notes:

  • lines 7-8: a MyError class derived from the Exception class. It adds no functionality to the latter. It is only there to provide a custom exception;
  • Line 13: The constructor has default values for its parameters. Thus, the operation p = Person() is equivalent to p = Person("x", "x", 0);
  • Lines 15–9: The first_name parameter is checked. It must not be empty. If it is, the MyError exception is thrown with an error message;
  • Lines 21–25: Same for the last_name;
  • lines 27–31: age verification;
  • lines 33-34: the __str__ function replaces the method previously called identite;
  • lines 38–42: instantiate a Person and display its identity;
  • line 39: instantiation;
  • line 40: display. The operation requires displaying the person p as a string. The Python interpreter then automatically calls the method p.__str__() if it exists. This method serves the same purpose as the toString() method in Java or .NET languages;
  • lines 41–42: handling of a potential MyError exception. Then displays the error message associated with the exception;
  • lines 44–48: same as above for a second instance of Person created with incorrect parameters;
  • lines 50–54: same as above for a third person instantiated with default parameters.

Results

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

5.5. Adding a method that acts as a second constructor


Program (classes_05)

#    -*- coding=utf-8 -*-

import re

# -------------------
#    a proprietary exception class
class MyError(Exception):
    pass

class Personne:
    #    class attributes
    #    undeclared - can be created dynamically

    #    manufacturer
    def __init__(self,prenom="x",nom="x",age=0):
         #  first name must be non-empty
        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]
        #  name must be non-empty
        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]
            #  age must be valid
        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):
        #  initializes the current object with a person p
        self.__init__(p.prenom,p.nom,p.age)

    def __str__(self):
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

#    ---------------------------------- main
#    a Person object
try:
    p0=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p0)
except MyError, erreur:
    print erreur
#    another object Nobody
try:
    p1=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p1)
except MyError, erreur:
    print erreur
#    another person
p2=Personne()
try:
    p2.initWithPersonne(p0)
    print "personne={0}".format(p2)
except MyError, erreur:
    print erreur

Notes:

  • The difference from the previous script is in lines 35–37. We have added the initWithPerson method. This method calls the __init__ constructor. Unlike in typed languages, it is not possible to have methods with the same name that are distinguished by the nature of their parameters or their return values. Therefore, it is not possible to have multiple constructors that would create the object from different parameters, in this case an object of type Person.

Results

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

5.6. A list of Person objects


Program (classes_06)

#   -*- coding=utf-8 -*-

class Personne:
    ...

#   ---------------------------------- main
#   create a list of person objects
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
#  identity of these persons
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Notes:

  • Lines 3-5: the Person class already described

Results

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

5.7. Creating a class derived from the Person class


Program (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)


#    ---------------------------------- main
#  create a list of Personne objects and derivatives
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
#  identity of these persons
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Notes:

  • lines 5-6: the Person class is already defined;
  • line 8: declares the Teacher class as a subclass of the Person class;
  • line 10: the constructor of the derived Teacher class must call the constructor of the parent Person class;
  • lines 21-22: to display group[i], the interpreter uses the method group[i].__str__(). The __str__() method used is that of the actual class of group[i], as shown in the results below.

Results

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

5.8. Creating a second class derived from the Person class


Program (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)

#    ---------------------------------- main
#  create a list of Personne objects and derivatives
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
#  identity of these persons
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Notes:

  • This script is similar to the previous one.

Results

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