5. Classes e objetos
Uma classe é o modelo a partir do qual os objetos são criados. Diz-se que um objeto é uma instância de uma classe.
5.1. Uma classe de objeto
Programa (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)
|
Notas:
- linha 4: outra forma de comentário. Precedido por três "", pode abranger várias linhas;
- linhas 3-4: uma classe de objeto vazia;
- linha 7: instanciação da classe Object;
- linha 17: cópia de referência. As variáveis obj1 e obj2 são dois ponteiros (referências) para o mesmo objeto.
Resultados
| objet1=[un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]
|
5.2. Uma classe Pessoa
Programa (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())
|
Notas:
- linhas 3-10: uma classe com um método;
- Linha 8: Todos os métodos de uma classe devem ter o objeto
self — que se refere ao objeto atual — como seu primeiro parâmetro.
Resultados
personne=[Paul,Langevin,48]
Programa (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())
|
Notas:
- linha 6: o construtor da classe chama-se __init__. Tal como acontece com outros métodos, o seu primeiro parâmetro é self;
- linha 18: Um objeto Pessoa é criado utilizando o construtor da classe.
Resultados
personne=[Paul,Langevin,48]
Programa (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
|
Notas:
- linhas 7-8: uma classe MyError derivada da classe Exception. Não acrescenta nenhuma funcionalidade a esta última. Está lá apenas para fornecer uma exceção personalizada;
- Linha 13: O construtor tem valores por defeito para os seus parâmetros. Assim, a operação p = Person() é equivalente a p = Person("x", "x", 0);
- Linhas 15–9: O parâmetro first_name é verificado. Não pode estar vazio. Se estiver, é lançada a exceção MyError com uma mensagem de erro;
- Linhas 21–25: O mesmo se aplica ao last_name;
- linhas 27–31: verificação da idade;
- linhas 33-34: a função __str__ substitui o método anteriormente chamado identite;
- linhas 38–42: instanciar uma Person e exibir a sua identidade;
- linha 39: instanciação;
- linha 40: exibição. A operação requer a exibição da pessoa p como uma string. O interpretador Python chama então automaticamente o método p.__str__() se este existir. Este método tem a mesma finalidade que o método toString() nas linguagens Java ou .NET;
- linhas 41–42: tratamento de uma potencial exceção MyError. Em seguida, exibe a mensagem de erro associada à exceção;
- linhas 44–48: igual ao acima para uma segunda instância de Person criada com parâmetros incorretos;
- linhas 50–54: igual ao acima para uma terceira instância de Person instanciada com parâmetros padrão.
Resultados
| personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[x,x,0]
|
5.5. Adicionar um método que funcione como um segundo construtor
Programa (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
|
Notas:
- A diferença em relação ao script anterior está nas linhas 35–37. Adicionámos o método
initWithPerson. Este método chama o construtor \_\_init\_\_. Ao contrário do que acontece nas linguagens tipadas, não é possível ter métodos com o mesmo nome que se distingam pela natureza dos seus parâmetros ou pelos seus valores de retorno. Por conseguinte, não é possível ter vários construtores que criem o objeto a partir de parâmetros diferentes, neste caso, um objeto do tipo Person.
Resultados
| personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[Paul,Langevin,48]
|
5.6. Uma lista de objetos Pessoa
Programa (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])
|
Notas:
- Linhas 3-5: a classe Person já descrita
Resultados
groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]
5.7. Criar uma classe derivada da classe Pessoa
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)
# ---------------------------------- 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])
|
Notas:
- linhas 5-6: a classe Person já está definida;
- linha 8: declara a classe Teacher como uma subclasse da classe Person;
- linha 10: o construtor da classe derivada Teacher deve chamar o construtor da classe pai Person;
- linhas 21-22: para exibir group[i], o interpretador utiliza o método group[i].__str__(). O método __str__() utilizado é o da classe real de group[i], conforme mostrado nos resultados abaixo.
Resultados
groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
5.8. Criação de uma segunda classe derivada da classe Pessoa
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)
# ---------------------------------- 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])
|
Notas:
- Este script é semelhante ao anterior.
Resultados
groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
groupe[2]=[Steve,Boer,22,iup2 qualite]