Skip to content

5. Classi e oggetti

La classe è lo stampo da cui vengono creati gli oggetti. Si dice che l’oggetto sia un’istanza di una classe.

  

5.1. Una classe Oggetto


Programma (classes_01)


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

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

# ogni variabile può avere attributi per definizione
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
# visualizza l'oggetto
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# modifica l'oggetto
obj1.attr2+=100
# visualizza l'oggetto
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# assegna il riferimento oggetto1 a oggetto2
obj2=obj1
# modifica l'oggetto 2
obj2.attr2=0
# visualizza entrambi gli oggetti
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)

Note:

  • riga 4: un altro tipo di commento. Questo, preceduto da tre "", può quindi estendersi su più righe;
  • righe 3-4: una classe oggetto vuota;
  • riga 7: istanziazione della classe Objet;
  • riga 17: copia di riferimenti. Le variabili obj1 e obj2 sono due puntatori (riferimenti) allo stesso oggetto.

Risultati

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

5.2. Una classe Persona


Programma (classes_02)


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

class Personne:
    # attributi della classe
    # non dichiarati - possono essere creati dinamicamente

    # metodo
    def identite(self):
        # a priori, utilizza attributi inesistenti
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

# ---------------------------------- main
# gli attributi sono pubblici e possono essere creati dinamicamente
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
# chiamata di un metodo
print "personne={0}\n".format(p.identite())

Note:

  • righe 3-10: una classe con un metodo;
  • riga 8: ogni metodo di una classe deve avere come primo parametro l'oggetto self, che indica l'oggetto corrente.

Risultati

personne=[Paul,Langevin,48]

5.3. La classe Persona con un costruttore


Programma (classes_03)


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

class Personne:
    
    # costruttore
    def __init__(self,prenom,nom,age):
        self.prenom=prenom;
        self.nom=nom;
        self.age=age;

    # metodo
    def identite(self):
        # a priori, utilizza attributi inesistenti
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

# ---------------------------------- main
# un oggetto Persona
p=Personne("Paul","Langevin",48)
# chiamata di un metodo
print "personne={0}\n".format(p.identite())

Note:

  • riga 6: il costruttore di una classe si chiama __init__. Come per gli altri metodi, il suo primo parametro è self;
  • riga 18: un oggetto Personne viene creato con il costruttore della classe.

Risultati

personne=[Paul,Langevin,48]

5.4. La classe Persona con controlli di validità nel costruttore


Programma (classes_04)


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

import re

# -------------------
# una classe di eccezione proprietaria
class MyError(Exception):
    pass

class Personne:
    
    # costruttore
    def __init__(self,prenom="x",nom="x",age=0):
         # il nome deve essere non vuoto
        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]
        # il cognome non deve essere vuoto
        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]
        # l'età deve essere valida
        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 oggetto Persona
try:
    p=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
# un altro oggetto Persona
try:
    p=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
# un'altra persona
try:
    p=Personne()
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur

Note:

  • righe 7-8: una classe MyError derivata dalla classe Exception. Non aggiunge alcuna funzionalità a quest'ultima. È presente solo per avere un'eccezione proprietaria;
  • riga 13: il costruttore ha valori predefiniti per i suoi parametri. Pertanto, l'operazione p=Personne() è equivalente a p=Personne("x","x",0);
  • righe 15-9: si analizza il parametro prenom. Deve essere non vuoto. In caso contrario, viene generata l’eccezione MyError con un messaggio di errore;
  • righe 21-25: lo stesso vale per il nome;
  • righe 27-31: verifica dell'età;
  • righe 33-34: la funzione __str__ sostituisce il metodo precedentemente denominato identite;
  • righe 38-42: istanziamento di una persona e successiva visualizzazione della sua identità;
  • riga 39: istanziazione;
  • riga 40: visualizzazione. L'operazione richiede di visualizzare la persona p sotto forma di stringa di caratteri. L'interprete Python chiama quindi automaticamente il metodo p.__str__(), se esiste. Questo metodo svolge la stessa funzione del metodo toString() in Java o nei linguaggi .NET;
  • righe 41-42: gestione di un'eventuale eccezione di tipo MyError. Viene quindi visualizzato il messaggio di errore associato all'eccezione;
  • righe 44-48: lo stesso vale per una seconda persona istanziata con parametri errati;
  • righe 50-54: lo stesso vale per una terza persona istanziata con i parametri predefiniti.

Risultati

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

5.5. Aggiunta di un metodo che funge da secondo costruttore


Programma (classes_05)


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

import re

# -------------------
# una classe di eccezione proprietaria
class MyError(Exception):
    pass

class Personne:
    # attributi della classe
    # non dichiarati - possono essere creati dinamicamente
    
    # costruttore
    def __init__(self,prenom="x",nom="x",age=0):
         # il nome deve essere diverso da vuoto
        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]
        # il cognome deve essere un valore non vuoto
        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]
            # l'età deve essere valida
        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):
        # inizializza l'oggetto corrente 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 oggetto Persona
try:
    p0=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p0)
except MyError, erreur:
    print erreur
# un altro oggetto Persona
try:
    p1=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p1)
except MyError, erreur:
    print erreur
# un'altra persona
p2=Personne()
try:
    p2.initWithPersonne(p0)
    print "personne={0}".format(p2)
except MyError, erreur:
    print erreur

Note:

  • la differenza rispetto allo script precedente si trova alle righe 35-37. È stato aggiunto il metodo initWithPersonne, che richiama il costruttore __init__. Non è possibile, come nei linguaggi tipizzati, avere metodi con lo stesso nome differenziati in base alla natura dei loro parametri o del loro risultato. Non è quindi possibile avere più costruttori che creino l’oggetto a partire da parametri diversi, in questo caso un oggetto di tipo Personne.

Risultati

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

5.6. Un elenco di oggetti Persona


Programma (classes_06)


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

class Personne:
    ...

# ---------------------------------- main
# creazione di un elenco di oggetti "Persona"
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
# identità di queste persone
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Note:

  • righe 3-5: la classe Personne già descritta

Risultati

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

5.7. Creazione di una classe derivata dalla classe Persona


Programma (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
# creazione di un elenco di oggetti "Persona" e derivati
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
# identità di queste persone
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Note:

  • righe 5-6: la classe Personne è già stata definita;
  • riga 8: dichiara la classe Enseignant come classe derivata dalla classe Persona;
  • riga 10: il costruttore della classe derivata Enseignant deve chiamare il costruttore della classe padre Personne;
  • righe 21-22: per visualizzare gruppo[i], l'interprete utilizza il metodo gruppo[i].__str__(). Il metodo __str__() utilizzato è quello della classe effettiva di groupe[i], come mostrano i risultati riportati di seguito.

Risultati

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

5.8. Creazione di una seconda classe derivata dalla classe Persona


Programma (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
# creazione di un elenco di oggetti "Persona" e derivati
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
# identità di queste persone
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Note:

  • questo script è analogo al precedente.

Risultati

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